Skip to content
Draft
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
921 changes: 921 additions & 0 deletions .openzeppelin/base-sepolia.json

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions contracts/ERC20Safe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ contract ERC20Safe is Initializable, BridgeRole, Pausable {
event ERC20Deposit(uint112 batchId, uint112 depositNonce);
event ERC20SCDeposit(uint112 indexed batchId, uint112 depositNonce, bytes callData);

uint16 public batchBlockLimitV2;
uint16 public batchSettleLimitV2;

function initialize() public initializer {
__BridgeRole_init();
__Pausable_init();
Expand All @@ -64,8 +67,8 @@ contract ERC20Safe is Initializable, BridgeRole, Pausable {

function __ERC20Safe__init_unchained() internal onlyInitializing {
batchSize = 10;
batchBlockLimit = 40;
batchSettleLimit = 40;
batchBlockLimitV2 = 40;
batchSettleLimitV2 = 40;
}

/**
Expand Down Expand Up @@ -123,22 +126,22 @@ contract ERC20Safe is Initializable, BridgeRole, Pausable {
@notice Updates the block number limit used to check if a batch is finalized for processing
@param newBatchBlockLimit New block number limit that will be set until a batch is considered final
*/
function setBatchBlockLimit(uint8 newBatchBlockLimit) external onlyAdmin {
require(newBatchBlockLimit <= batchSettleLimit, "Cannot increase batch block limit over settlement limit");
batchBlockLimit = newBatchBlockLimit;
function setBatchBlockLimit(uint16 newBatchBlockLimit) external onlyAdmin {
require(newBatchBlockLimit <= batchSettleLimitV2, "Cannot increase batch block limit over settlement limit");
batchBlockLimitV2 = newBatchBlockLimit;
}

/**
@notice Updates the settle number limit used to determine if a batch is final
@param newBatchSettleLimit New block settle limit that will be set until a batch is considered final
*/
function setBatchSettleLimit(uint8 newBatchSettleLimit) external onlyAdmin whenPaused {
function setBatchSettleLimit(uint16 newBatchSettleLimit) external onlyAdmin whenPaused {
require(!isAnyBatchInProgress(), "Cannot change batchSettleLimit with pending batches");
require(
newBatchSettleLimit >= batchBlockLimit,
newBatchSettleLimit >= batchBlockLimitV2,
"Cannot decrease batchSettleLimit under the value of batch block limit"
);
batchSettleLimit = newBatchSettleLimit;
batchSettleLimitV2 = newBatchSettleLimit;
}

/**
Expand Down Expand Up @@ -389,14 +392,14 @@ contract ERC20Safe is Initializable, BridgeRole, Pausable {
}

function _isBatchFinal(Batch memory batch) private view returns (bool) {
return (batch.lastUpdatedBlockNumber + batchSettleLimit) < block.number;
return (batch.lastUpdatedBlockNumber + batchSettleLimitV2) < block.number;
}

function _isBatchProgessOver(uint16 depCount, uint64 blockNumber) private view returns (bool) {
if (depCount == 0) {
return false;
}
return (blockNumber + batchBlockLimit) < block.number;
return (blockNumber + batchBlockLimitV2) < block.number;
}

function _shouldCreateNewBatch() private view returns (bool) {
Expand Down
43 changes: 42 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ import "./tasks/get-batch-deposits";
import "./tasks/get-quorum";
import "./tasks/get-statuses-after-execution";
import "./tasks/depositSC";
import "./tasks/set-batch-settle-limit-on-safe"
import "./tasks/set-batch-settle-limit"
import "./tasks/set-batch-settle-limit-on-bridge"
import "./tasks/deploy";
import "./tasks/token-balance-query"
import "./tasks/get-relayers"
import "./tasks/get-token-properties"
import "./tasks/reset-total-balance"
import "./tasks/mintburn-test-tokens"
import "./tasks/get-safe-parameters"


import { resolve } from "path";
Expand Down Expand Up @@ -102,6 +104,43 @@ function getETHConfig(network: string, withLedger: boolean): NetworkUserConfig {
return config;
}

function getBaseConfig(network: string, withLedger: boolean): NetworkUserConfig {
let config: any

if (withLedger) {
config = {
ledgerAccounts: [
"0x4408D9f40b9e45d5bE27256Ad71453DeEF043910",
],
ledgerOptions: {
derivationFunction: (x: string) => `m/44'/60'/0'/0/${x}`
},
};
} else {
config = {
accounts: {
count: 12,
mnemonic,
path: "m/44'/60'/0'/0",
initialIndex: Number(initialindex),
},
};
}

switch (network) {
case "testnet":
config.url = "https://base-sepolia.infura.io/v3/" + infuraApiKey;
break;
case "mainnet":
config.url = "https://base-mainnet.infura.io/v3/" + infuraApiKey;
break;
default:
throw new Error("invalid config option for eth chain");
}

return config;
}

function getBSCConfig(network: string, withLedger: boolean): NetworkUserConfig {
let config: any

Expand Down Expand Up @@ -190,6 +229,8 @@ const config: HardhatUserConfig = {
mainnet_bsc_ledger: getBSCConfig("mainnet", true),
mumbai: getPolygonConfig("testnet"),
mainnet_polygon: getPolygonConfig("mainnet"),
testnet_base: getBaseConfig("testnet", false),
testnet_base_ledger: getBaseConfig("testnet", true),
},
paths: {
artifacts: "./artifacts",
Expand Down
19 changes: 19 additions & 0 deletions tasks/deploy/force-import-bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "@nomicfoundation/hardhat-toolbox";

task("force-import-bridge", "Imports the Bridge configuration in the .openzeppelin directory. IMPORTANT: use this on the current deployed version of the code")
.addOptionalParam("price", "Gas price in gwei for this transaction", undefined)
.setAction(async (taskArgs, hre) => {
const [adminWallet] = await hre.ethers.getSigners();
console.log("Admin Public Address: ", adminWallet.address);

const fs = require("fs");
const filename = "setup.config.json";
const config = JSON.parse(fs.readFileSync(filename, "utf8"));
const bridgeAddress = config["bridge"];
console.log("Bridge deployed to: ", bridgeAddress);

const factory = (await hre.ethers.getContractFactory("Bridge")).connect(adminWallet);
await hre.upgrades.forceImport(bridgeAddress, factory)

console.log("Bridge imported");
});
19 changes: 19 additions & 0 deletions tasks/deploy/force-import-safe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "@nomicfoundation/hardhat-toolbox";

task("force-import-safe", "Imports the ERC20Safe configuration in the .openzeppelin directory. IMPORTANT: use this on the current deployed version of the code")
.addOptionalParam("price", "Gas price in gwei for this transaction", undefined)
.setAction(async (taskArgs, hre) => {
const [adminWallet] = await hre.ethers.getSigners();
console.log("Admin Public Address: ", adminWallet.address);

const fs = require("fs");
const filename = "setup.config.json";
const config = JSON.parse(fs.readFileSync(filename, "utf8"));
const safeAddress = config["erc20Safe"];
console.log("ERC20Safe deployed to: ", safeAddress);

const factory = (await hre.ethers.getContractFactory("ERC20Safe")).connect(adminWallet);
await hre.upgrades.forceImport(safeAddress, factory)

console.log("ERC20Safe imported");
});
2 changes: 2 additions & 0 deletions tasks/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ import "./evil-erc";
import "./mint-burn-tokens";
import "./upgrade-safe"
import "./approve-non-zero-tokens";
import "./force-import-safe"
import "./force-import-bridge"
34 changes: 34 additions & 0 deletions tasks/get-safe-parameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import "@nomicfoundation/hardhat-toolbox";
import fs from "fs";

task("get-safe-parameters", "Get the Safe contract parameters").setAction(async (taskArgs, hre) => {
const fs = require("fs");
const config = JSON.parse(fs.readFileSync("setup.config.json", "utf8"));
const safeAddress = config["erc20Safe"];

const safeContractFactory = await hre.ethers.getContractFactory("ERC20Safe");
const contract = safeContractFactory.attach(safeAddress)

console.log(`Safe contract: ${safeAddress}`);

let value = await contract.batchesCount();
console.log(`Batches count: ${value}`);

value = await contract.depositsCount();
console.log(`Deposits count: ${value}`);

value = await contract.batchSize();
console.log(`Batch size: ${value}`);

value = await contract.batchSettleLimit();
console.log(`Batch settle limit: ${value}`);

value = await contract.batchBlockLimit();
console.log(`Batch block limit: ${value}`);

const isPaused = await contract.paused();
console.log(`Is paused: ${isPaused}`);

const setBridgeAddress = await contract.bridge()
console.log(`Set bridge address: ${setBridgeAddress}`);
});
12 changes: 6 additions & 6 deletions tasks/set-batch-settle-limit-on-bridge.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import "@nomicfoundation/hardhat-toolbox";

task("set-batch-settle-limit-on-bridge", "Sets a new batch block limit")
task("set-batch-settle-limit-on-bridge", "Sets a new batch block limit - for MultiversX finality check")
.addParam("blocks", "new batch settle limit")
.addOptionalParam("price", "Gas price in gwei for this transaction", undefined)
.setAction(async (taskArgs, hre) => {
const fs = require("fs");
const filename = "setup.config.json";
let config = JSON.parse(fs.readFileSync(filename, "utf8"));
const [adminWallet] = await hre.ethers.getSigners();
const safeAddress = config["erc20Safe"];
const safeContractFactory = await hre.ethers.getContractFactory("ERC20Safe");
const safe = safeContractFactory.attach(safeAddress).connect(adminWallet);
const bridgeAddress = config["bridge"];
const bridgeContractFactory = await hre.ethers.getContractFactory("Bridge");
const bridge = bridgeContractFactory.attach(bridgeAddress).connect(adminWallet);

if (taskArgs.price) {
await safe.setBatchBlockLimit(taskArgs.blocks, { gasPrice: taskArgs.price * 1000000000 });
await bridge.setBatchSettleLimit(taskArgs.blocks, { gasPrice: taskArgs.price * 1000000000 });
} else {
await safe.setBatchBlockLimit(taskArgs.blocks);
await bridge.setBatchSettleLimit(taskArgs.blocks);
}
config.batchBlockLimit = taskArgs.blocks;
fs.writeFileSync(filename, JSON.stringify(config));
Expand Down
20 changes: 20 additions & 0 deletions tasks/set-batch-settle-limit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import "@nomicfoundation/hardhat-toolbox";
import { getDeployOptions } from "./args/deployOptions";

task("set-batch-settle-limit", "Sets a new batch settle limit")
.addParam("blocks", "new batch settle limit")
.addOptionalParam("price", "Gas price in gwei for this transaction", undefined)
.setAction(async (taskArgs, hre) => {
const fs = require("fs");
const filename = "setup.config.json";
let config = JSON.parse(fs.readFileSync(filename, "utf8"));
const [adminWallet] = await hre.ethers.getSigners();
const safeAddress = config["erc20Safe"];
const safeContractFactory = await hre.ethers.getContractFactory("ERC20Safe");
const safe = safeContractFactory.attach(safeAddress).connect(adminWallet);

await safe.setBatchSettleLimit(taskArgs.blocks, getDeployOptions(taskArgs));

config.batchBlockLimit = taskArgs.blocks;
fs.writeFileSync(filename, JSON.stringify(config));
});
12 changes: 6 additions & 6 deletions test/Safe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ describe("ERC20Safe", function () {
describe("ERC20Safe - setting batch block limit works as expected", async function () {
it("is default correct", async function () {
const tenMinutes = 40;
expect(await safe.batchBlockLimit()).to.eq(tenMinutes);
expect(await safe.batchBlockLimitV2()).to.eq(tenMinutes);
});
it("updates the batch time limit", async function () {
const eight = 8;
await safe.setBatchBlockLimit(eight);
expect(await safe.batchBlockLimit()).to.equal(eight);
expect(await safe.batchBlockLimitV2()).to.equal(eight);
});
it("reverts", async function () {
await expect(safe.connect(otherWallet).setBatchBlockLimit(30)).to.be.revertedWith(
Expand All @@ -81,7 +81,7 @@ describe("ERC20Safe", function () {
describe("ERC20Safe - setting batch settle limit works as expected", async function () {
it("is default correct", async function () {
const tenMinutes = 40;
expect(await safe.batchSettleLimit()).to.eq(tenMinutes);
expect(await safe.batchSettleLimitV2()).to.eq(tenMinutes);
});
it("reverts", async function () {
await expect(safe.connect(adminWallet).setBatchSettleLimit(50)).to.be.revertedWith("Pausable: not paused");
Expand Down Expand Up @@ -147,7 +147,7 @@ describe("ERC20Safe", function () {

const batchSettleLimit = 50;
await safe.connect(adminWallet).setBatchSettleLimit(batchSettleLimit);
expect(await safe.batchSettleLimit()).to.equal(batchSettleLimit);
expect(await safe.batchSettleLimitV2()).to.equal(batchSettleLimit);

await safe.unpause();
});
Expand Down Expand Up @@ -308,7 +308,7 @@ describe("ERC20Safe", function () {
});

it("creates new batches as time passes", async function () {
const batchBlockLimit = parseInt((await safe.batchBlockLimit()).toString());
const batchBlockLimit = parseInt((await safe.batchBlockLimitV2()).toString());
await safe.setBatchSize(2);
expect(await safe.batchesCount()).to.be.eq(0);

Expand Down Expand Up @@ -452,7 +452,7 @@ describe("ERC20Safe", function () {

it("returns batch only after final", async function () {
await safe.setBatchSize(3);
const batchBlockLimit = parseInt((await safe.batchBlockLimit()).toString());
const batchBlockLimit = parseInt((await safe.batchBlockLimitV2()).toString());

await safe.deposit(
genericERC20.address,
Expand Down