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

Deployment of FORT on Arbitrum and Arbitrum Sepolia #270

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
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
746 changes: 746 additions & 0 deletions .openzeppelin/unknown-421614.json

Large diffs are not rendered by default.

94 changes: 94 additions & 0 deletions contracts/token/FortaBridgedArbitrum.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// SPDX-License-Identifier: UNLICENSED
// See Forta Network License: https://github.com/forta-network/forta-contracts/blob/master/LICENSE.md

pragma solidity ^0.8.9;

import "./FortaCommon.sol";
import "./IArbToken.sol";

/**
* This version of the Forta token is living on the Arbitrum Layer 2.
*
* On Arbitrum, when tokens are bridged from the L1, the `L2ERC20Gateway` will call the
* {bridgeMint} function, which will mint corresponding tokens on the L2 side. The total supply
* on the L2 is expected to match the amount of locked tokens on the L1.
*
* In order to bridge tokens back from the L2 to L1, any user
* can call the {outBoundTransfer} function on the `L2GatewayRouter`. This will burn tokens here,
* emitting a burn event (Transfer event from the user to address(0)) in the process.
*/
contract FortaBridgedArbitrum is FortaCommon, IArbToken {
address private l1TokenAddress;
address private l2ERC20Gateway;

error MintOnlyByL2ERC20Gateway();
error BurnOnlyByL2ERC20Gateway();

/**
* @notice Initializer method, access point to initialize inheritance tree.
* @param __admin address that will be ADMIN_ROLE.
* @param __l1TokenAddress address of L1 FORT token.
* @param __l2ERC20Gateway address of Arbitrum ERC20Gateway.
*/
function initialize(address __admin, address __l1TokenAddress, address __l2ERC20Gateway) public initializer {
if (__l1TokenAddress == address(0)) revert ZeroAddress("l1TokenAddress");
if (__l2ERC20Gateway == address(0)) revert ZeroAddress("l2ERC20Gateway");

__FortaCommon_init(__admin);
l1TokenAddress = __l1TokenAddress;
l2ERC20Gateway = __l2ERC20Gateway;
}

/**
* @notice Allows the L2ERC20Gateway on this network to mint tokens,
* as part of bridging form L1.
* @dev Only callable by L2ERC20Gateway
* @param account Address to bridge tokens to.
* @param amount Amount of tokens to bridge.
*/
function bridgeMint(address account, uint256 amount) external {
if (msg.sender != l2ERC20Gateway) revert MintOnlyByL2ERC20Gateway();

_mint(account, amount);
}

/**
* @notice Allows the L2ERC20Gateway on this network to burn tokens,
* as part of bridging to L1.
* @dev Only callable by L2ERC20Gateway
* @param account Address to bridge tokens from.
* @param amount Amount of tokens to bridge.
*/
function bridgeBurn(address account, uint256 amount) external {
if (msg.sender != l2ERC20Gateway) revert BurnOnlyByL2ERC20Gateway();

_burn(account, amount);
}

/**
* @notice L1 token address getter
* @return Address of layer 1 token
*/
function l1Address() external view returns (address) {
return l1TokenAddress;
}

/**
* @notice Contract version
* @dev Since FortaCommon is IVersioned, Forta is deployed in L1 and FortaBridgedPolygon and FortaBridgedArbitrum in L2,
* we need to implement the interface with a method instead of immutable variable.
* @return version of FORT deployed in Arbitrum L2
*/
function version() external pure returns(string memory) {
return "0.1.0";
}

/**
* 49
* - 1 l1TokenAddress
* - 1 l2ERC20Gateway
* --------------------------
* 47 __gap
*/
uint256[47] private __gap;
}
44 changes: 44 additions & 0 deletions contracts/token/IArbToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: Apache-2.0

/*
* Copyright 2020, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary
* for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation).
* @dev For the token to be compatible out of the box with the tooling available (e.g., the Arbitrum bridge), it is
* recommended to keep the implementation of this interface as close as possible to the `TestArbCustomToken` example.
*/

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface IArbToken {
/**
* @notice should increase token supply by amount, and should (probably) only be callable by the L1 bridge.
*/
function bridgeMint(address account, uint256 amount) external;

/**
* @notice should decrease token supply by amount, and should (probably) only be callable by the L1 bridge.
*/
function bridgeBurn(address account, uint256 amount) external;

/**
* @return address of layer 1 token
*/
function l1Address() external view returns (address);
}
14 changes: 12 additions & 2 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ module.exports = {
mainnet: argv.etherscan,
sepolia: argv.etherscan,
polygon: argv.polyscan,
basesepolia: argv.basescan
arbitrumOne: argv.arbiscan,
basesepolia: argv.basescan,
arbitrumsepolia: argv.arbiscan
},
customChains: [
{
Expand All @@ -75,6 +77,14 @@ module.exports = {
apiURL: "https://api-sepolia.basescan.org/api",
browserURL: "https://sepolia.basescan.org/"
}
},
{
network: "arbitrumsepolia",
chainId: 421614,
urls: {
apiURL: "https://api-sepolia.arbiscan.io/api",
browserURL: "https://sepolia.arbiscan.io/"
}
}
]
},
Expand Down Expand Up @@ -103,7 +113,7 @@ const accountsForNetwork = (name) => [argv[`${name}Mnemonic`] && { mnemonic: arg
Object.assign(
module.exports.networks,
Object.fromEntries(
['mainnet', 'ropsten', 'rinkeby', 'goerli', 'kovan', 'polygon', 'mumbai', 'amoy', 'sepolia', 'basesepolia', 'local']
['mainnet', 'ropsten', 'rinkeby', 'goerli', 'kovan', 'polygon', 'arbitrum', 'mumbai', 'amoy', 'sepolia', 'basesepolia', 'arbitrumsepolia', 'local']
.map((name) => [name, { url: argv[`${name}Node`], accounts: accountsForNetwork(name), gasPrice: argv[`${name}GasPrice`] || 'auto' }])
.filter(([, { url }]) => url)
),
Expand Down
1 change: 1 addition & 0 deletions releases/1.2.15/arbitrum/config/deploy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions releases/1.2.15/arbitrum/output/deployed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
17 changes: 17 additions & 0 deletions releases/1.2.15/arbitrumsepolia/config/deploy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"FortaBridgedArbitrum": {
"impl": {
"init-args": [
"0x233BAc002bF01DA9FEb9DE57Ff7De5B3820C1a24",
"0x95d9a757ad9C25999ffE93f3067221F04ce1Cc79",
"0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502"
],
"opts": {
"unsafe-allow": [
"delegatecall"
],
"constructor-args": []
}
}
}
}
18 changes: 18 additions & 0 deletions releases/1.2.15/arbitrumsepolia/output/deployed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"forta-bridged-arbitrum-deploy-tx": "0xbfd0cb53f6ae0d50834da210d5803b21ec2fad53f7685527a575ea137691e09e",
"forta-bridged-arbitrum": {
"address": "0x2441Ce5eB269505f30F6F434D21E039438aaC342",
"impl": {
"address": "0x95d9a757ad9C25999ffE93f3067221F04ce1Cc79",
"constructor-args": [],
"init-args": [
"0x233BAc002bF01DA9FEb9DE57Ff7De5B3820C1a24",
"0x95d9a757ad9C25999ffE93f3067221F04ce1Cc79",
"0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502"
],
"name": "FortaBridgedArbitrum",
"timeout": 1200000,
"version": "0.1.0"
}
}
}
9 changes: 9 additions & 0 deletions releases/1.2.15/index.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
title: FORT Arbitrum deployment
network: arbitrumsepolia
# network: arbitrum (for mainnet)
deploy: deploy-and-prepare-upgrade 1.2.15
verify: verify-deployed
finish: propose-admin
description: |
## Deployed new implementations on Arbitrum testnet:
- FORT token
1 change: 1 addition & 0 deletions releases/deployments/42161.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
18 changes: 18 additions & 0 deletions releases/deployments/421614.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"forta-bridged-arbitrum": {
"address": "0x2441Ce5eB269505f30F6F434D21E039438aaC342",
"impl": {
"address": "0x95d9a757ad9C25999ffE93f3067221F04ce1Cc79",
"constructor-args": [],
"init-args": [
"0x233BAc002bF01DA9FEb9DE57Ff7De5B3820C1a24",
"0x95d9a757ad9C25999ffE93f3067221F04ce1Cc79",
"0x6e244cD02BBB8a6dbd7F626f05B2ef82151Ab502"
],
"name": "FortaBridgedArbitrum",
"timeout": 1200000,
"version": "0.1.0"
}
},
"forta-bridged-arbitrum-deploy-tx": "0xbfd0cb53f6ae0d50834da210d5803b21ec2fad53f7685527a575ea137691e09e"
}
2 changes: 2 additions & 0 deletions releases/deployments/multisigs.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"mumbai": "0x19AD705930B6695812c921f08b16F7DfAF59A536",
"polygon": "0x30ceaeC1d8Ed347B91d45077721c309242db3D6d",
"arbitrum": "0x0000000000000000000000000000000000000000",
"sepolia": "0x0000000000000000000000000000000000000000",
"basesepolia": "0x4e22284F3aDC3c023c9D8bb4Fbb27fbb96ef6d5e",
"arbitrumsepolia": "0x0000000000000000000000000000000000000000",
"local": "0x233BAc002bF01DA9FEb9DE57Ff7De5B3820C1a24"
}
2 changes: 2 additions & 0 deletions releases/deployments/relayers.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"mumbai": "0x2832d78949b9963f44ba2a3f15ac1ac56eeb2676",
"sepolia": "0x0000000000000000000000000000000000000000",
"basesepolia": "0xa17AdDd061ba541823832A983E78490CE2787e95",
"arbitrumsepolia": "0x0000000000000000000000000000000000000000",
"polygon": "0x15d3c7e811582be09bb8673cd603bb2f22d1e47b",
"arbitrum": "0x0000000000000000000000000000000000000000",
"local": "0x233BAc002bF01DA9FEb9DE57Ff7De5B3820C1a24"
}
4 changes: 4 additions & 0 deletions scripts/utils/contractHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ const getBlockExplorerDomain = (hre) => {
case 'polygon':
case 'matic':
return 'polygonscan.com';
case 'arbitrum':
return 'arbiscan.io';
case 'mumbai':
return 'mumbai.polygonscan.com';
case 'amoy':
Expand All @@ -152,6 +154,8 @@ const getBlockExplorerDomain = (hre) => {
return 'sepolia.etherscan.io';
case 'basesepolia':
return 'sepolia.basescan.org'
case 'arbitrumsepolia':
return 'sepolia.arbiscan.io';
}
};

Expand Down
2 changes: 2 additions & 0 deletions scripts/utils/deploymentFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ const CHAIN_NAME = {
1: 'mainnet',
5: 'goerli',
137: 'polygon',
42161: 'arbitrum',
80001: 'mumbai',
80002: 'amoy',
84532: 'basesepolia',
31337: 'local',
421614: 'arbitrumsepolia',
11155111: 'sepolia'
};

Expand Down
Loading