Skip to content

Commit

Permalink
support billing config (#12310)
Browse files Browse the repository at this point in the history
* support billing config

* use IERC20
  • Loading branch information
shileiwill authored and ogtownsend committed Mar 13, 2024
1 parent 3f21cba commit 5d20ecd
Show file tree
Hide file tree
Showing 18 changed files with 2,453 additions and 1,418 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const checksum = utils.id(abis.join(''))
fs.writeFileSync(`${tmpDest}`, JSON.stringify(combinedABI))

const cmd = `
cat ${tmpDest} | pnpm abi-to-sol --solidity-version ^0.8.4 --license MIT > ${srcDest} IAutomationRegistryMaster;
cat ${tmpDest} | pnpm abi-to-sol --solidity-version ^0.8.4 --license MIT > ${srcDest} IAutomationRegistryMaster2_3;
echo "// abi-checksum: ${checksum}" | cat - ${srcDest} > ${tmpDest} && mv ${tmpDest} ${srcDest};
pnpm prettier --write ${srcDest};
`
Expand Down

Large diffs are not rendered by default.

215 changes: 202 additions & 13 deletions contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ pragma solidity 0.8.19;
import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol";
import {BaseTest} from "./BaseTest.t.sol";
import {AutomationRegistry2_3} from "../v2_3/AutomationRegistry2_3.sol";
import {AutomationRegistryBase2_3} 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 {IAutomationRegistryMaster} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol";
import {IAutomationRegistryMaster2_3, AutomationRegistryBase2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol";
import {ChainModuleBase} from "../../chains/ChainModuleBase.sol";

contract AutomationRegistry2_3_SetUp is BaseTest {
Expand All @@ -29,7 +28,7 @@ contract AutomationRegistry2_3_SetUp is BaseTest {
address[] internal s_valid_transmitters;
address[] internal s_registrars;

IAutomationRegistryMaster internal registryMaster;
IAutomationRegistryMaster2_3 internal registryMaster;

function setUp() public override {
s_valid_transmitters = new address[](4);
Expand All @@ -55,7 +54,7 @@ contract AutomationRegistry2_3_SetUp is BaseTest {
ZERO_ADDRESS
);
AutomationRegistryLogicA2_3 logicA2_3 = new AutomationRegistryLogicA2_3(logicB2_3);
registryMaster = IAutomationRegistryMaster(
registryMaster = IAutomationRegistryMaster2_3(
address(new AutomationRegistry2_3(AutomationRegistryLogicB2_3(address(logicA2_3))))
);
}
Expand All @@ -77,7 +76,7 @@ contract AutomationRegistry2_3_CheckUpkeep is AutomationRegistry2_3_SetUp {

// 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));
vm.expectRevert(abi.encodeWithSelector(IAutomationRegistryMaster2_3.OnlySimulatedBackend.selector));
registryMaster.checkUpkeep(id, triggerData);
}
}
Expand All @@ -95,12 +94,9 @@ contract AutomationRegistry2_3_SetConfig is AutomationRegistry2_3_SetUp {
bytes offchainConfig
);

function testSetConfigSuccess() public {
(uint32 configCount, , ) = registryMaster.latestConfigDetails();
assertEq(configCount, 0);
ChainModuleBase module = new ChainModuleBase();

AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({
address module = address(new ChainModuleBase());
AutomationRegistryBase2_3.OnchainConfig cfg =
AutomationRegistryBase2_3.OnchainConfig({
paymentPremiumPPB: 10_000,
flatFeeMicroLink: 40_000,
checkGasLimit: 5_000_000,
Expand All @@ -119,10 +115,27 @@ contract AutomationRegistry2_3_SetConfig is AutomationRegistry2_3_SetUp {
chainModule: module,
reorgProtectionEnabled: true
});

function testSetConfigSuccess() public {
(uint32 configCount, , ) = registryMaster.latestConfigDetails();
assertEq(configCount, 0);

address billingTokenAddress = address(0x1111111111111111111111111111111111111111);
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,
flatFeeMicroLink: 20_000,
priceFeed: 0x2222222222222222222222222222222222222222
});

bytes memory onchainConfigBytes = abi.encode(cfg);
bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs);

uint256 a = 1234;
address b = address(0);
address b = ZERO_ADDRESS;
bytes memory offchainConfigBytes = abi.encode(a, b);
bytes32 configDigest = _configDigestFromConfigData(
block.chainid,
Expand Down Expand Up @@ -153,7 +166,59 @@ contract AutomationRegistry2_3_SetConfig is AutomationRegistry2_3_SetUp {
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytes,
onchainConfigBytesWithBilling,
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);

AutomationRegistryBase2_3.BillingConfig memory config = registryMaster.getBillingTokenConfig(billingTokenAddress);
assertEq(config.gasFeePPB, 5_000);
assertEq(config.flatFeeMicroLink, 20_000);
assertEq(config.priceFeed, 0x2222222222222222222222222222222222222222);

address[] memory tokens = registryMaster.getBillingTokens();
assertEq(tokens.length, 1);
}

function testSetConfigMultipleBillingConfigsSuccess() public {
(uint32 configCount, , ) = registryMaster.latestConfigDetails();
assertEq(configCount, 0);

address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111);
address billingTokenAddress2 = address(0x1111111111111111111111111111111111111112);
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,
flatFeeMicroLink: 20_001,
priceFeed: 0x2222222222222222222222222222222222222221
});
billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({
gasFeePPB: 5_002,
flatFeeMicroLink: 20_002,
priceFeed: 0x2222222222222222222222222222222222222222
});

bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs);

uint256 a = 1234;
address b = ZERO_ADDRESS;
bytes memory offchainConfigBytes = abi.encode(a, b);

registryMaster.setConfig(
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytesWithBilling,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);
Expand All @@ -163,6 +228,130 @@ contract AutomationRegistry2_3_SetConfig is AutomationRegistry2_3_SetUp {
assertEq(signers, s_valid_signers);
assertEq(transmitters, s_valid_transmitters);
assertEq(f, F);

AutomationRegistryBase2_3.BillingConfig memory config1 = registryMaster.getBillingTokenConfig(billingTokenAddress1);
assertEq(config1.gasFeePPB, 5_001);
assertEq(config1.flatFeeMicroLink, 20_001);
assertEq(config1.priceFeed, 0x2222222222222222222222222222222222222221);

AutomationRegistryBase2_3.BillingConfig memory config2 = registryMaster.getBillingTokenConfig(billingTokenAddress2);
assertEq(config2.gasFeePPB, 5_002);
assertEq(config2.flatFeeMicroLink, 20_002);
assertEq(config2.priceFeed, 0x2222222222222222222222222222222222222222);

address[] memory tokens = registryMaster.getBillingTokens();
assertEq(tokens.length, 2);
}

function testSetConfigTwiceAndLastSetOverwrites() public {
(uint32 configCount, , ) = registryMaster.latestConfigDetails();
assertEq(configCount, 0);

// BillingConfig1
address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111);
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,
flatFeeMicroLink: 20_001,
priceFeed: 0x2222222222222222222222222222222222222221
});

bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1);

// BillingConfig2
address billingTokenAddress2 = address(0x1111111111111111111111111111111111111112);
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,
flatFeeMicroLink: 20_002,
priceFeed: 0x2222222222222222222222222222222222222222
});

bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg, billingTokens2, billingConfigs2);

uint256 a = 1234;
address b = ZERO_ADDRESS;
bytes memory offchainConfigBytes = abi.encode(a, b);

// set config once
registryMaster.setConfig(
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytesWithBilling1,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);

// set config twice
registryMaster.setConfig(
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytesWithBilling2,
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);

AutomationRegistryBase2_3.BillingConfig memory config2 = registryMaster.getBillingTokenConfig(billingTokenAddress2);
assertEq(config2.gasFeePPB, 5_002);
assertEq(config2.flatFeeMicroLink, 20_002);
assertEq(config2.priceFeed, 0x2222222222222222222222222222222222222222);

address[] memory tokens = registryMaster.getBillingTokens();
assertEq(tokens.length, 1);
}

function testSetConfigDuplicateBillingConfigFailure() public {
(uint32 configCount, , ) = registryMaster.latestConfigDetails();
assertEq(configCount, 0);

address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111);
address billingTokenAddress2 = address(0x1111111111111111111111111111111111111111);
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,
flatFeeMicroLink: 20_001,
priceFeed: 0x2222222222222222222222222222222222222221
});
billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({
gasFeePPB: 5_002,
flatFeeMicroLink: 20_002,
priceFeed: 0x2222222222222222222222222222222222222222
});

bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs);

uint256 a = 1234;
address b = ZERO_ADDRESS;
bytes memory offchainConfigBytes = abi.encode(a, b);

// expect revert because of duplicate tokens
vm.expectRevert(abi.encodeWithSelector(IAutomationRegistryMaster2_3.DuplicateEntry.selector));
registryMaster.setConfig(
s_valid_signers,
s_valid_transmitters,
F,
onchainConfigBytesWithBilling,
OFFCHAIN_CONFIG_VERSION,
offchainConfigBytes
);
}

function _configDigestFromConfigData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.19;

import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol";
import {IAutomationRegistryMaster} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.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";
Expand Down Expand Up @@ -76,7 +76,7 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC
}

struct RegistrarConfig {
IAutomationRegistryMaster AutomationRegistry;
IAutomationRegistryMaster2_3 AutomationRegistry;
uint96 minLINKJuels;
}

Expand Down Expand Up @@ -292,7 +292,7 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC
function setConfig(address AutomationRegistry, uint96 minLINKJuels) public onlyOwner {
s_config = RegistrarConfig({
minLINKJuels: minLINKJuels,
AutomationRegistry: IAutomationRegistryMaster(AutomationRegistry)
AutomationRegistry: IAutomationRegistryMaster2_3(AutomationRegistry)
});
emit ConfigChanged(AutomationRegistry, minLINKJuels);
}
Expand Down Expand Up @@ -437,7 +437,7 @@ contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC
* @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event
*/
function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) {
IAutomationRegistryMaster AutomationRegistry = s_config.AutomationRegistry;
IAutomationRegistryMaster2_3 AutomationRegistry = s_config.AutomationRegistry;
uint256 upkeepId = AutomationRegistry.registerUpkeep(
params.upkeepContract,
params.gasLimit,
Expand Down
Loading

0 comments on commit 5d20ecd

Please sign in to comment.