Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions contracts/ConfigStore.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// 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 {
// 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.
* @param value Value to update.
*/
function updateGlobalConfig(bytes32 key, string calldata value) external onlyOwner {
globalConfig[key] = value;
emit UpdatedGlobalConfig(key, value);
}
}
29 changes: 0 additions & 29 deletions contracts/RateModelStore.sol

This file was deleted.

38 changes: 38 additions & 0 deletions test/ConfigStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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 token config", async function () {
const l1Token = randomAddress();
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(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(configStore.connect(other).updateGlobalConfig(key, value)).to.be.revertedWith(
"Ownable: caller is not the owner"
);
await expect(configStore.connect(owner).updateGlobalConfig(key, value))
.to.emit(configStore, "UpdatedGlobalConfig")
.withArgs(key, value);
expect(await configStore.globalConfig(key)).to.equal(value);
});
});
18 changes: 18 additions & 0 deletions test/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
};