Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgradable contracts implementation #43

Merged
merged 17 commits into from
Aug 22, 2024
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
1,260 changes: 630 additions & 630 deletions .yarn/releases/yarn-1.22.22.cjs

Large diffs are not rendered by default.

63 changes: 44 additions & 19 deletions abi/contracts/Bridge/Bridge.abi.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
[
{
"inputs": [
{
"internalType": "address[]",
"name": "board",
"type": "address[]"
},
{
"internalType": "uint256",
"name": "initialQuorum",
"type": "uint256"
},
{
"internalType": "contract ERC20Safe",
"name": "erc20Safe",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
"inputs": [],
"name": "InvalidInitialization",
"type": "error"
},
{
"inputs": [],
"name": "NotInitializing",
"type": "error"
},
{
"anonymous": false,
Expand All @@ -39,6 +28,19 @@
"name": "AdminRoleTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint64",
"name": "version",
"type": "uint64"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -389,6 +391,29 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address[]",
"name": "board",
"type": "address[]"
},
{
"internalType": "uint256",
"name": "initialQuorum",
"type": "uint256"
},
{
"internalType": "contract ERC20Safe",
"name": "erc20Safe",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down
157 changes: 156 additions & 1 deletion abi/contracts/Bridge/Bridge.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion abi/contracts/Bridge/Bridge.hex

Large diffs are not rendered by default.

67 changes: 46 additions & 21 deletions abi/contracts/Bridge/Bridge.json

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions abi/contracts/ERC20Safe/ERC20Safe.abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
"name": "FailedInnerCall",
"type": "error"
},
{
"inputs": [],
"name": "InvalidInitialization",
"type": "error"
},
{
"inputs": [],
"name": "NotInitializing",
"type": "error"
},
{
"inputs": [
{
Expand Down Expand Up @@ -119,6 +129,19 @@
"name": "ERC20SCDeposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint64",
"name": "version",
"type": "uint64"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -534,6 +557,13 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "isAnyBatchInProgress",
Expand Down
157 changes: 156 additions & 1 deletion abi/contracts/ERC20Safe/ERC20Safe.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion abi/contracts/ERC20Safe/ERC20Safe.hex

Large diffs are not rendered by default.

34 changes: 32 additions & 2 deletions abi/contracts/ERC20Safe/ERC20Safe.json

Large diffs are not rendered by default.

67 changes: 46 additions & 21 deletions abi/contracts/MintBurnERC20/MintBurnERC20.abi.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,4 @@
[
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "uint8",
"name": "providedNumDecimals",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AccessControlBadConfirmation",
Expand Down Expand Up @@ -138,6 +117,16 @@
"name": "ERC20InvalidSpender",
"type": "error"
},
{
"inputs": [],
"name": "InvalidInitialization",
"type": "error"
},
{
"inputs": [],
"name": "NotInitializing",
"type": "error"
},
{
"anonymous": false,
"inputs": [
Expand All @@ -163,6 +152,19 @@
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint64",
"name": "version",
"type": "uint64"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -461,6 +463,29 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "uint8",
"name": "providedNumDecimals",
"type": "uint8"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down
157 changes: 156 additions & 1 deletion abi/contracts/MintBurnERC20/MintBurnERC20.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion abi/contracts/MintBurnERC20/MintBurnERC20.hex

Large diffs are not rendered by default.

71 changes: 48 additions & 23 deletions abi/contracts/MintBurnERC20/MintBurnERC20.json

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import "./SharedStructs.sol";
import "./ERC20Safe.sol";
import "./access/RelayerRole.sol";
Expand All @@ -22,7 +24,7 @@ In order to use it:
@dev This contract mimics a multisign contract by sending the signatures from all
relayers with the execute call, in order to save gas.
*/
contract Bridge is RelayerRole, Pausable {
contract Bridge is Initializable, RelayerRole, Pausable {
/*============================ EVENTS ============================*/
event QuorumChanged(uint256 quorum);

Expand All @@ -31,10 +33,10 @@ contract Bridge is RelayerRole, Pausable {
string private constant executeTransferAction = "ExecuteBatchedTransfer";
string private constant prefix = "\x19Ethereum Signed Message:\n32";
uint256 private constant minimumQuorum = 3;
uint256 public batchSettleBlockCount = 40;
uint256 public batchSettleBlockCount;

uint256 public quorum;
ERC20Safe internal immutable safe;
ERC20Safe internal safe;

mapping(uint256 => bool) public executedBatches;
mapping(uint256 => CrossTransferStatus) public crossTransferStatuses;
Expand All @@ -48,14 +50,21 @@ contract Bridge is RelayerRole, Pausable {
* - add/remove relayers
* - add/remove tokens that can be bridged
*/
constructor(address[] memory board, uint256 initialQuorum, ERC20Safe erc20Safe) {
function initialize(address[] memory board, uint256 initialQuorum, ERC20Safe erc20Safe) public virtual initializer {
__RelayerRole_init();
__Bridge__init_unchained(board, initialQuorum, erc20Safe);
}

function __Bridge__init_unchained(address[] memory board, uint256 initialQuorum, ERC20Safe erc20Safe) internal onlyInitializing {
require(initialQuorum >= minimumQuorum, "Quorum is too low.");
require(board.length >= initialQuorum, "The board should be at least the quorum size.");

_addRelayers(board);

quorum = initialQuorum;
safe = erc20Safe;

batchSettleBlockCount = 40;
}

/**
Expand Down
25 changes: 19 additions & 6 deletions contracts/ERC20Safe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./SharedStructs.sol";
import "./access/BridgeRole.sol";
import "./lib/BoolTokenTransfer.sol";
import "./lib/Pausable.sol";
import "./lib/BoolTokenTransfer.sol";

interface IMintableERC20 is IERC20 {
function mint(address to, uint256 amount) external;
Expand All @@ -27,16 +28,16 @@ In order to use it:
@dev The deposits are requested by the Bridge, and in order to save gas spent by the relayers
they will be batched either by time (batchTimeLimit) or size (batchSize).
*/
contract ERC20Safe is BridgeRole, Pausable {
contract ERC20Safe is Initializable, BridgeRole, Pausable {
using SafeERC20 for IERC20;
using BoolTokenTransfer for IERC20;

uint64 public batchesCount;
uint64 public depositsCount;
uint16 public batchSize = 10;
uint16 public batchSize;
uint16 private constant maxBatchSize = 100;
uint8 public batchBlockLimit = 40;
uint8 public batchSettleLimit = 40;
uint8 public batchBlockLimit;
uint8 public batchSettleLimit;

mapping(uint256 => Batch) public batches;
mapping(address => bool) public whitelistedTokens;
Expand All @@ -52,6 +53,18 @@ contract ERC20Safe is BridgeRole, Pausable {
event ERC20Deposit(uint112 batchId, uint112 depositNonce);
event ERC20SCDeposit(uint112 indexed batchId, uint112 depositNonce, bytes callData);

function initialize() public initializer {
__BridgeRole_init();
__Pausable_init();
__ERC20Safe__init_unchained();
}

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

/**
@notice Whitelist a token. Only whitelisted tokens can be bridged.
@param token Address of the ERC20 token that will be whitelisted
Expand Down
18 changes: 13 additions & 5 deletions contracts/MintBurnERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@

pragma solidity ^0.8.20;

import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";

contract MintBurnERC20 is ERC20, AccessControl, ERC20Burnable {
contract MintBurnERC20 is ERC20Upgradeable, AccessControlUpgradeable, ERC20BurnableUpgradeable {
// Create a new role identifier for the minter role
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
uint8 private numDecimals;

error CallerNotMinter(address caller);

constructor(string memory name, string memory symbol, uint8 providedNumDecimals) ERC20(name, symbol) {
function initialize(string memory name, string memory symbol, uint8 providedNumDecimals) public initializer {
__ERC20_init(name, symbol);
__AccessControl_init();
__ERC20Burnable_init();

__MintBurnERC20__init_unchained(providedNumDecimals);
}

function __MintBurnERC20__init_unchained(uint8 providedNumDecimals) internal onlyInitializing {
numDecimals = providedNumDecimals;
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
Expand Down
10 changes: 8 additions & 2 deletions contracts/access/AdminRole.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an admin) that can be granted exclusive access to
Expand All @@ -14,15 +16,19 @@ pragma solidity ^0.8.20;
* `onlyAdmin`, which can be applied to your functions to restrict their use to
* the admin.
*/
abstract contract AdminRole {
abstract contract AdminRole is Initializable {
address private _admin;

event AdminRoleTransferred(address indexed previousAdmin, address indexed newAdmin);

/**
* @dev Initializes the contract setting the deployer as the initial admin.
*/
constructor() {
function __AdminRole_init() internal onlyInitializing {
__AdminRole_init_unchained();
}

function __AdminRole_init_unchained() internal onlyInitializing {
address msgSender = msg.sender;
_admin = msgSender;
emit AdminRoleTransferred(address(0), msgSender);
Expand Down
Loading
Loading