From 5aa7e4901aa23a558ca370e44347c9a2f36d985e Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Tue, 3 May 2022 10:56:57 -0400 Subject: [PATCH 1/4] feat: Change RateModelStore => ConfigStore and add fields --- contracts/ConfigStore.sol | 61 ++++++++++++++++++++++++++++++++++++ contracts/RateModelStore.sol | 29 ----------------- test/ConfigStore.ts | 45 ++++++++++++++++++++++++++ test/constants.ts | 18 +++++++++++ 4 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 contracts/ConfigStore.sol delete mode 100644 contracts/RateModelStore.sol create mode 100644 test/ConfigStore.ts diff --git a/contracts/ConfigStore.sol b/contracts/ConfigStore.sol new file mode 100644 index 000000000..ffed3d647 --- /dev/null +++ b/contracts/ConfigStore.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity ^0.8.0; + +import "@uma/core/contracts/common/implementation/MultiCaller.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title Allows admin to set and update configuration settings for full contract system. These settings are designed + * to be consumed by off-chain bots, rather than by other contracts. + * @dev This contract should not perform any validation on the setting values and should be owned by the governance + * system of the full contract suite.. + */ +contract ConfigStore is Ownable, MultiCaller { + // This will be queried by off-chain agents that need to compute realized LP fee %'s for deposit quote + // timestamps. This contract does not validate the shape of the rate model, which is stored as a string to + // enable arbitrary data encoding via a stringified JSON. Every L1 token enabled in the HubPool will be mapped + // to one rate model. + mapping(address => string) public l1TokenRateModels; + + // This will be queried by an off-chain dataworker to determine whether to send tokens from the HubPool to the + // SpokePool via a pool rebalance, or just to save the amount to send in "runningBalances". + mapping(address => uint256) public l1TokenTransferThresholds; + + // General dictionary where admin can store global uint variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and + // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query. + mapping(bytes32 => uint256) public uintGlobalConfig; + + event UpdatedRateModel(address indexed l1Token, string rateModel); + event UpdatedTransferThreshold(address indexed l1Token, uint256 transferThreshold); + event UpdatedGlobalConfig(bytes32 indexed key, uint256 value); + + /** + * @notice Updates rate model string for L1 token. + * @param l1Token the l1 token rate model to update. + * @param rateModel the updated rate model. + */ + function updateRateModel(address l1Token, string memory rateModel) external onlyOwner { + l1TokenRateModels[l1Token] = rateModel; + emit UpdatedRateModel(l1Token, rateModel); + } + + /** + * @notice Updates token transfer threshold percentage for L1 token. + * @param l1Token the l1 token rate model to update. + * @param transferThresholdPct the updated transfer threshold percentage. + */ + function updateTransferThreshold(address l1Token, uint256 transferThresholdPct) external onlyOwner { + l1TokenTransferThresholds[l1Token] = transferThresholdPct; + emit UpdatedTransferThreshold(l1Token, transferThresholdPct); + } + + /** + * @notice Updates global uint config. + * @param key Key to update. + * @param value Value to update. + */ + function updateUintGlobalConfig(bytes32 key, uint256 value) external onlyOwner { + uintGlobalConfig[key] = value; + emit UpdatedGlobalConfig(key, value); + } +} diff --git a/contracts/RateModelStore.sol b/contracts/RateModelStore.sol deleted file mode 100644 index 72e8b6f7a..000000000 --- a/contracts/RateModelStore.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity ^0.8.0; - -import "@uma/core/contracts/common/implementation/MultiCaller.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title Maps rate model objects to L1 token. - * @dev This contract is designed to be queried by off-chain relayers that need to compute realized LP fee %'s before - * submitting relay transactions to a BridgePool contract. Therefore, this contract does not perform any validation on - * the shape of the rate model, which is stored as a string to enable arbitrary data encoding via a stringified JSON - * object. This leaves this contract unopionated on the parameters within the rate model, enabling governance to adjust - * the structure in the future. - */ -contract RateModelStore is Ownable, MultiCaller { - mapping(address => string) public l1TokenRateModels; - - event UpdatedRateModel(address indexed l1Token, string rateModel); - - /** - * @notice Updates rate model string for L1 token. - * @param l1Token the l1 token rate model to update. - * @param rateModel the updated rate model. - */ - function updateRateModel(address l1Token, string memory rateModel) external onlyOwner { - l1TokenRateModels[l1Token] = rateModel; - emit UpdatedRateModel(l1Token, rateModel); - } -} diff --git a/test/ConfigStore.ts b/test/ConfigStore.ts new file mode 100644 index 000000000..0910878a6 --- /dev/null +++ b/test/ConfigStore.ts @@ -0,0 +1,45 @@ +import { getContractFactory, SignerWithAddress, utf8ToHex, expect, Contract, ethers, randomAddress } from "./utils"; +import * as constants from "./constants"; + +let configStore: Contract; +let owner: SignerWithAddress, other: SignerWithAddress; + +describe("Config Store", function () { + beforeEach(async function () { + [owner, other] = await ethers.getSigners(); + configStore = await (await getContractFactory("ConfigStore", owner)).deploy(); + }); + + it("Updating rate model", async function () { + const l1Token = randomAddress(); + const stringifiedRateModel = JSON.stringify(constants.sampleRateModel); + await expect(configStore.connect(other).updateRateModel(l1Token, stringifiedRateModel)).to.be.revertedWith( + "Ownable: caller is not the owner" + ); + await expect(configStore.connect(owner).updateRateModel(l1Token, stringifiedRateModel)) + .to.emit(configStore, "UpdatedRateModel") + .withArgs(l1Token, stringifiedRateModel); + expect(await configStore.l1TokenRateModels(l1Token)).to.equal(stringifiedRateModel); + }); + it("Updating token transfer threshold", async function () { + const l1Token = randomAddress(); + await expect( + configStore.connect(other).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold) + ).to.be.revertedWith("Ownable: caller is not the owner"); + await expect(configStore.connect(owner).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold)) + .to.emit(configStore, "UpdatedTransferThreshold") + .withArgs(l1Token, constants.l1TokenTransferThreshold.toString()); + expect(await configStore.l1TokenTransferThresholds(l1Token)).to.equal(constants.l1TokenTransferThreshold); + }); + it("Updating global uint config", async function () { + const key = utf8ToHex("MAX_POOL_REBALANCE_LEAF_SIZE"); + const value = constants.maxRefundsPerRelayerRefundLeaf; + await expect(configStore.connect(other).updateUintGlobalConfig(key, value)).to.be.revertedWith( + "Ownable: caller is not the owner" + ); + await expect(configStore.connect(owner).updateUintGlobalConfig(key, value)) + .to.emit(configStore, "UpdatedGlobalConfig") + .withArgs(key, value); + expect(await configStore.uintGlobalConfig(key)).to.equal(value); + }); +}); diff --git a/test/constants.ts b/test/constants.ts index d4f849a61..df3490304 100644 --- a/test/constants.ts +++ b/test/constants.ts @@ -82,3 +82,21 @@ export const sampleL2Gas = 2000000; export const sampleL2MaxSubmissionCost = toWei("0.01"); export const sampleL2GasPrice = 5e9; + +// Max number of refunds in relayer refund leaf for a { repaymentChainId, L2TokenAddress }. +export const maxRefundsPerRelayerRefundLeaf = 3; + +// Max number of L1 tokens for a chain ID in a pool rebalance leaf. +export const maxL1TokensPerPoolRebalanceLeaf = 3; + +// Once running balances hits this number for an L1 token, net send amount should be set to running +// balances to transfer tokens to the spoke pool. +export const l1TokenTransferThreshold = toWei(100); + +// DAI's Rate model. +export const sampleRateModel = { + UBar: toWei(0.8).toString(), + R0: toWei(0.04).toString(), + R1: toWei(0.07).toString(), + R2: toWei(0.75).toString(), +}; From 50b47845ba0c1934ce67dbae2b0d948df6f85574 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Tue, 3 May 2022 13:41:43 -0400 Subject: [PATCH 2/4] Rename to separate contracts --- contracts/GlobalConfigStore.sol | 29 ++++++++++++++++ .../{ConfigStore.sol => TokenConfigStore.sol} | 19 ++--------- test/ConfigStore.ts | 33 ++++++++++--------- 3 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 contracts/GlobalConfigStore.sol rename contracts/{ConfigStore.sol => TokenConfigStore.sol} (75%) diff --git a/contracts/GlobalConfigStore.sol b/contracts/GlobalConfigStore.sol new file mode 100644 index 000000000..03c1c3ff0 --- /dev/null +++ b/contracts/GlobalConfigStore.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity ^0.8.0; + +import "@uma/core/contracts/common/implementation/MultiCaller.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title Allows admin to set and update configuration settings for full contract system. These settings are designed + * to be consumed by off-chain bots, rather than by other contracts. + * @dev This contract should not perform any validation on the setting values and should be owned by the governance + * system of the full contract suite.. + */ +contract GlobalConfigStore is Ownable, MultiCaller { + // General dictionary where admin can store global variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and + // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query. + mapping(bytes32 => string) public globalConfig; + + event UpdatedGlobalConfig(bytes32 indexed key, string value); + + /** + * @notice Updates global uint config. + * @param key Key to update. + * @param value Value to update. + */ + function updateGlobalConfig(bytes32 key, string value) external onlyOwner { + uintGlobalConfig[key] = value; + emit UpdatedGlobalConfig(key, value); + } +} diff --git a/contracts/ConfigStore.sol b/contracts/TokenConfigStore.sol similarity index 75% rename from contracts/ConfigStore.sol rename to contracts/TokenConfigStore.sol index ffed3d647..6bca095cd 100644 --- a/contracts/ConfigStore.sol +++ b/contracts/TokenConfigStore.sol @@ -8,9 +8,9 @@ import "@openzeppelin/contracts/access/Ownable.sol"; * @title Allows admin to set and update configuration settings for full contract system. These settings are designed * to be consumed by off-chain bots, rather than by other contracts. * @dev This contract should not perform any validation on the setting values and should be owned by the governance - * system of the full contract suite.. + * system of the full contract suite. */ -contract ConfigStore is Ownable, MultiCaller { +contract TokenConfigStore is Ownable, MultiCaller { // This will be queried by off-chain agents that need to compute realized LP fee %'s for deposit quote // timestamps. This contract does not validate the shape of the rate model, which is stored as a string to // enable arbitrary data encoding via a stringified JSON. Every L1 token enabled in the HubPool will be mapped @@ -21,13 +21,8 @@ contract ConfigStore is Ownable, MultiCaller { // SpokePool via a pool rebalance, or just to save the amount to send in "runningBalances". mapping(address => uint256) public l1TokenTransferThresholds; - // General dictionary where admin can store global uint variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and - // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query. - mapping(bytes32 => uint256) public uintGlobalConfig; - event UpdatedRateModel(address indexed l1Token, string rateModel); event UpdatedTransferThreshold(address indexed l1Token, uint256 transferThreshold); - event UpdatedGlobalConfig(bytes32 indexed key, uint256 value); /** * @notice Updates rate model string for L1 token. @@ -48,14 +43,4 @@ contract ConfigStore is Ownable, MultiCaller { l1TokenTransferThresholds[l1Token] = transferThresholdPct; emit UpdatedTransferThreshold(l1Token, transferThresholdPct); } - - /** - * @notice Updates global uint config. - * @param key Key to update. - * @param value Value to update. - */ - function updateUintGlobalConfig(bytes32 key, uint256 value) external onlyOwner { - uintGlobalConfig[key] = value; - emit UpdatedGlobalConfig(key, value); - } } diff --git a/test/ConfigStore.ts b/test/ConfigStore.ts index 0910878a6..0870a4792 100644 --- a/test/ConfigStore.ts +++ b/test/ConfigStore.ts @@ -1,45 +1,46 @@ import { getContractFactory, SignerWithAddress, utf8ToHex, expect, Contract, ethers, randomAddress } from "./utils"; import * as constants from "./constants"; -let configStore: Contract; +let tokenConfigStore: Contract, globalConfigStore: Contract; let owner: SignerWithAddress, other: SignerWithAddress; describe("Config Store", function () { beforeEach(async function () { [owner, other] = await ethers.getSigners(); - configStore = await (await getContractFactory("ConfigStore", owner)).deploy(); + tokenConfigStore = await (await getContractFactory("TokenConfigStore", owner)).deploy(); + globalConfigStore = await (await getContractFactory("GlobalConfigStore", owner)).deploy(); }); it("Updating rate model", async function () { const l1Token = randomAddress(); const stringifiedRateModel = JSON.stringify(constants.sampleRateModel); - await expect(configStore.connect(other).updateRateModel(l1Token, stringifiedRateModel)).to.be.revertedWith( + await expect(tokenConfigStore.connect(other).updateRateModel(l1Token, stringifiedRateModel)).to.be.revertedWith( "Ownable: caller is not the owner" ); - await expect(configStore.connect(owner).updateRateModel(l1Token, stringifiedRateModel)) - .to.emit(configStore, "UpdatedRateModel") + await expect(tokenConfigStore.connect(owner).updateRateModel(l1Token, stringifiedRateModel)) + .to.emit(tokenConfigStore, "UpdatedRateModel") .withArgs(l1Token, stringifiedRateModel); - expect(await configStore.l1TokenRateModels(l1Token)).to.equal(stringifiedRateModel); + expect(await tokenConfigStore.l1TokenRateModels(l1Token)).to.equal(stringifiedRateModel); }); it("Updating token transfer threshold", async function () { const l1Token = randomAddress(); await expect( - configStore.connect(other).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold) + tokenConfigStore.connect(other).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold) ).to.be.revertedWith("Ownable: caller is not the owner"); - await expect(configStore.connect(owner).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold)) - .to.emit(configStore, "UpdatedTransferThreshold") + await expect(tokenConfigStore.connect(owner).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold)) + .to.emit(tokenConfigStore, "UpdatedTransferThreshold") .withArgs(l1Token, constants.l1TokenTransferThreshold.toString()); - expect(await configStore.l1TokenTransferThresholds(l1Token)).to.equal(constants.l1TokenTransferThreshold); + expect(await tokenConfigStore.l1TokenTransferThresholds(l1Token)).to.equal(constants.l1TokenTransferThreshold); }); - it("Updating global uint config", async function () { + it("Updating global config", async function () { const key = utf8ToHex("MAX_POOL_REBALANCE_LEAF_SIZE"); - const value = constants.maxRefundsPerRelayerRefundLeaf; - await expect(configStore.connect(other).updateUintGlobalConfig(key, value)).to.be.revertedWith( + const value = constants.maxRefundsPerRelayerRefundLeaf.toString(); + await expect(globalConfigStore.connect(other).updateUintGlobalConfig(key, value)).to.be.revertedWith( "Ownable: caller is not the owner" ); - await expect(configStore.connect(owner).updateUintGlobalConfig(key, value)) - .to.emit(configStore, "UpdatedGlobalConfig") + await expect(globalConfigStore.connect(owner).updateUintGlobalConfig(key, value)) + .to.emit(globalConfigStore, "UpdatedGlobalConfig") .withArgs(key, value); - expect(await configStore.uintGlobalConfig(key)).to.equal(value); + expect(await globalConfigStore.uintGlobalConfig(key)).to.equal(value); }); }); From 70407c2d19b20416f277fc9197bcbff507c98184 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Tue, 3 May 2022 13:48:11 -0400 Subject: [PATCH 3/4] fix test --- contracts/GlobalConfigStore.sol | 6 +++--- test/ConfigStore.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/GlobalConfigStore.sol b/contracts/GlobalConfigStore.sol index 03c1c3ff0..887470be2 100644 --- a/contracts/GlobalConfigStore.sol +++ b/contracts/GlobalConfigStore.sol @@ -18,12 +18,12 @@ contract GlobalConfigStore is Ownable, MultiCaller { event UpdatedGlobalConfig(bytes32 indexed key, string value); /** - * @notice Updates global uint config. + * @notice Updates global config. * @param key Key to update. * @param value Value to update. */ - function updateGlobalConfig(bytes32 key, string value) external onlyOwner { - uintGlobalConfig[key] = value; + function updateGlobalConfig(bytes32 key, string calldata value) external onlyOwner { + globalConfig[key] = value; emit UpdatedGlobalConfig(key, value); } } diff --git a/test/ConfigStore.ts b/test/ConfigStore.ts index 0870a4792..450f1503a 100644 --- a/test/ConfigStore.ts +++ b/test/ConfigStore.ts @@ -35,12 +35,12 @@ describe("Config Store", function () { it("Updating global config", async function () { const key = utf8ToHex("MAX_POOL_REBALANCE_LEAF_SIZE"); const value = constants.maxRefundsPerRelayerRefundLeaf.toString(); - await expect(globalConfigStore.connect(other).updateUintGlobalConfig(key, value)).to.be.revertedWith( + await expect(globalConfigStore.connect(other).updateGlobalConfig(key, value)).to.be.revertedWith( "Ownable: caller is not the owner" ); - await expect(globalConfigStore.connect(owner).updateUintGlobalConfig(key, value)) + await expect(globalConfigStore.connect(owner).updateGlobalConfig(key, value)) .to.emit(globalConfigStore, "UpdatedGlobalConfig") .withArgs(key, value); - expect(await globalConfigStore.uintGlobalConfig(key)).to.equal(value); + expect(await globalConfigStore.globalConfig(key)).to.equal(value); }); }); From 596e5bf0fc1826dcad77bab5c3320d6d00319961 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Wed, 4 May 2022 08:49:26 -0400 Subject: [PATCH 4/4] collapse contracts --- ...{GlobalConfigStore.sol => ConfigStore.sol} | 17 ++++++- contracts/TokenConfigStore.sol | 46 ------------------- test/ConfigStore.ts | 40 +++++++--------- 3 files changed, 32 insertions(+), 71 deletions(-) rename contracts/{GlobalConfigStore.sol => ConfigStore.sol} (63%) delete mode 100644 contracts/TokenConfigStore.sol diff --git a/contracts/GlobalConfigStore.sol b/contracts/ConfigStore.sol similarity index 63% rename from contracts/GlobalConfigStore.sol rename to contracts/ConfigStore.sol index 887470be2..ce86aca6d 100644 --- a/contracts/GlobalConfigStore.sol +++ b/contracts/ConfigStore.sol @@ -10,13 +10,28 @@ import "@openzeppelin/contracts/access/Ownable.sol"; * @dev This contract should not perform any validation on the setting values and should be owned by the governance * system of the full contract suite.. */ -contract GlobalConfigStore is Ownable, MultiCaller { +contract ConfigStore is Ownable, MultiCaller { + // General dictionary where admin can associate variables with specific L1 tokens, like the Rate Model and Token + // Transfer Thresholds. + mapping(address => string) public l1TokenConfig; + // General dictionary where admin can store global variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query. mapping(bytes32 => string) public globalConfig; + event UpdatedTokenConfig(address indexed key, string value); event UpdatedGlobalConfig(bytes32 indexed key, string value); + /** + * @notice Updates token config. + * @param l1Token the l1 token address to update value for. + * @param value Value to update. + */ + function updateTokenConfig(address l1Token, string memory value) external onlyOwner { + l1TokenConfig[l1Token] = value; + emit UpdatedTokenConfig(l1Token, value); + } + /** * @notice Updates global config. * @param key Key to update. diff --git a/contracts/TokenConfigStore.sol b/contracts/TokenConfigStore.sol deleted file mode 100644 index 6bca095cd..000000000 --- a/contracts/TokenConfigStore.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity ^0.8.0; - -import "@uma/core/contracts/common/implementation/MultiCaller.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title Allows admin to set and update configuration settings for full contract system. These settings are designed - * to be consumed by off-chain bots, rather than by other contracts. - * @dev This contract should not perform any validation on the setting values and should be owned by the governance - * system of the full contract suite. - */ -contract TokenConfigStore is Ownable, MultiCaller { - // This will be queried by off-chain agents that need to compute realized LP fee %'s for deposit quote - // timestamps. This contract does not validate the shape of the rate model, which is stored as a string to - // enable arbitrary data encoding via a stringified JSON. Every L1 token enabled in the HubPool will be mapped - // to one rate model. - mapping(address => string) public l1TokenRateModels; - - // This will be queried by an off-chain dataworker to determine whether to send tokens from the HubPool to the - // SpokePool via a pool rebalance, or just to save the amount to send in "runningBalances". - mapping(address => uint256) public l1TokenTransferThresholds; - - event UpdatedRateModel(address indexed l1Token, string rateModel); - event UpdatedTransferThreshold(address indexed l1Token, uint256 transferThreshold); - - /** - * @notice Updates rate model string for L1 token. - * @param l1Token the l1 token rate model to update. - * @param rateModel the updated rate model. - */ - function updateRateModel(address l1Token, string memory rateModel) external onlyOwner { - l1TokenRateModels[l1Token] = rateModel; - emit UpdatedRateModel(l1Token, rateModel); - } - - /** - * @notice Updates token transfer threshold percentage for L1 token. - * @param l1Token the l1 token rate model to update. - * @param transferThresholdPct the updated transfer threshold percentage. - */ - function updateTransferThreshold(address l1Token, uint256 transferThresholdPct) external onlyOwner { - l1TokenTransferThresholds[l1Token] = transferThresholdPct; - emit UpdatedTransferThreshold(l1Token, transferThresholdPct); - } -} diff --git a/test/ConfigStore.ts b/test/ConfigStore.ts index 450f1503a..c600bbce1 100644 --- a/test/ConfigStore.ts +++ b/test/ConfigStore.ts @@ -1,46 +1,38 @@ import { getContractFactory, SignerWithAddress, utf8ToHex, expect, Contract, ethers, randomAddress } from "./utils"; import * as constants from "./constants"; -let tokenConfigStore: Contract, globalConfigStore: Contract; +let configStore: Contract; let owner: SignerWithAddress, other: SignerWithAddress; describe("Config Store", function () { beforeEach(async function () { [owner, other] = await ethers.getSigners(); - tokenConfigStore = await (await getContractFactory("TokenConfigStore", owner)).deploy(); - globalConfigStore = await (await getContractFactory("GlobalConfigStore", owner)).deploy(); + configStore = await (await getContractFactory("ConfigStore", owner)).deploy(); }); - it("Updating rate model", async function () { + it("Updating token config", async function () { const l1Token = randomAddress(); - const stringifiedRateModel = JSON.stringify(constants.sampleRateModel); - await expect(tokenConfigStore.connect(other).updateRateModel(l1Token, stringifiedRateModel)).to.be.revertedWith( + const value = JSON.stringify({ + rateModel: constants.sampleRateModel, + tokenTransferThreshold: constants.l1TokenTransferThreshold, + }); + await expect(configStore.connect(other).updateTokenConfig(l1Token, value)).to.be.revertedWith( "Ownable: caller is not the owner" ); - await expect(tokenConfigStore.connect(owner).updateRateModel(l1Token, stringifiedRateModel)) - .to.emit(tokenConfigStore, "UpdatedRateModel") - .withArgs(l1Token, stringifiedRateModel); - expect(await tokenConfigStore.l1TokenRateModels(l1Token)).to.equal(stringifiedRateModel); - }); - it("Updating token transfer threshold", async function () { - const l1Token = randomAddress(); - await expect( - tokenConfigStore.connect(other).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold) - ).to.be.revertedWith("Ownable: caller is not the owner"); - await expect(tokenConfigStore.connect(owner).updateTransferThreshold(l1Token, constants.l1TokenTransferThreshold)) - .to.emit(tokenConfigStore, "UpdatedTransferThreshold") - .withArgs(l1Token, constants.l1TokenTransferThreshold.toString()); - expect(await tokenConfigStore.l1TokenTransferThresholds(l1Token)).to.equal(constants.l1TokenTransferThreshold); + await expect(configStore.connect(owner).updateTokenConfig(l1Token, value)) + .to.emit(configStore, "UpdatedTokenConfig") + .withArgs(l1Token, value); + expect(await configStore.l1TokenConfig(l1Token)).to.equal(value); }); it("Updating global config", async function () { const key = utf8ToHex("MAX_POOL_REBALANCE_LEAF_SIZE"); const value = constants.maxRefundsPerRelayerRefundLeaf.toString(); - await expect(globalConfigStore.connect(other).updateGlobalConfig(key, value)).to.be.revertedWith( + await expect(configStore.connect(other).updateGlobalConfig(key, value)).to.be.revertedWith( "Ownable: caller is not the owner" ); - await expect(globalConfigStore.connect(owner).updateGlobalConfig(key, value)) - .to.emit(globalConfigStore, "UpdatedGlobalConfig") + await expect(configStore.connect(owner).updateGlobalConfig(key, value)) + .to.emit(configStore, "UpdatedGlobalConfig") .withArgs(key, value); - expect(await globalConfigStore.globalConfig(key)).to.equal(value); + expect(await configStore.globalConfig(key)).to.equal(value); }); });