Skip to content

Commit

Permalink
Merge pull request #330 from 0xPolygonHermez/feature/sovereign-bridge
Browse files Browse the repository at this point in the history
Sovereign bridge implementation
  • Loading branch information
ignasirv authored Nov 5, 2024
2 parents 2b044eb + ddfd159 commit 63a89fe
Show file tree
Hide file tree
Showing 28 changed files with 8,448 additions and 1,636 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
node-version: [18.x]
node-version: [20.x]

steps:
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-push-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [20.x]

steps:
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [20.x]

steps:
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [20.x]

steps:
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ typechain-types/
create_rollup_parameters.json

docker/deploymentOutput

.DS_Store
6 changes: 6 additions & 0 deletions contracts/PolygonZkEVMGlobalExitRootL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ contract PolygonZkEVMGlobalExitRootL2 is IBasePolygonZkEVMGlobalExitRoot {
// PolygonZkEVM Bridge address
address public immutable bridgeAddress;

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
*/
uint256[50] private _gap;

/**
* @param _bridgeAddress PolygonZkEVMBridge contract address
*/
Expand Down
20 changes: 20 additions & 0 deletions contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ interface IBasePolygonZkEVMGlobalExitRoot {
*/
error OnlyAllowedContracts();

/**
* @dev Thrown when the caller is not the coinbase neither the globalExitRootUpdater
*/
error OnlyGlobalExitRootUpdater();

/**
* @dev Thrown when trying to insert a global exit root that is already set
*/
error GlobalExitRootAlreadySet();

/**
* @dev Thrown when trying to remove more global exit roots thank inserted
*/
error NotEnoughGlobalExitRootsInserted();

/**
* @dev Thrown when trying to remove a ger that is not the last one
*/
error NotLastInsertedGlobalExitRoot();

function updateExitRoot(bytes32 newRollupExitRoot) external;

function globalExitRootMap(
Expand Down
64 changes: 53 additions & 11 deletions contracts/v2/PolygonZkEVMBridgeV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,16 @@ contract PolygonZkEVMBridgeV2 is
bytes public gasTokenMetadata;

// WETH address
// @note WETH address will only be present when the native token is not ether, but another gasToken.
// This variable is set at the initialization of the contract in case there's a gas token differnet than ether, (gasTokenAddress != address(0) ) so a new wrapped Token will be deployed to handle ether that came from other networks
TokenWrapped public WETHToken;

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
*/
uint256[50] private _gap;

/**
* @dev Emitted when bridge assets or messages to another network
*/
Expand Down Expand Up @@ -238,7 +246,7 @@ contract PolygonZkEVMBridgeV2 is
// In case ether is the native token, WETHToken will be 0, and the address 0 is already checked
if (token == address(WETHToken)) {
// Burn tokens
TokenWrapped(token).burn(msg.sender, amount);
_bridgeWrappedAsset(TokenWrapped(token), amount);

// Both origin network and originTokenAddress will be 0
// Metadata will be empty
Expand All @@ -250,8 +258,7 @@ contract PolygonZkEVMBridgeV2 is
if (tokenInfo.originTokenAddress != address(0)) {
// The token is a wrapped token from another network

// Burn tokens
TokenWrapped(token).burn(msg.sender, amount);
_bridgeWrappedAsset(TokenWrapped(token), amount);

originTokenAddress = tokenInfo.originTokenAddress;
originNetwork = tokenInfo.originNetwork;
Expand Down Expand Up @@ -364,7 +371,7 @@ contract PolygonZkEVMBridgeV2 is
}

// Burn wETH tokens
WETHToken.burn(msg.sender, amountWETH);
_bridgeWrappedAsset(WETHToken, amountWETH);

_bridgeMessage(
destinationNetwork,
Expand Down Expand Up @@ -437,7 +444,7 @@ contract PolygonZkEVMBridgeV2 is
* @param mainnetExitRoot Mainnet exit root
* @param rollupExitRoot Rollup exit root
* @param originNetwork Origin network
* @param originTokenAddress Origin token address, 0 address is reserved for ether
* @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token
* @param destinationNetwork Network destination
* @param destinationAddress Address destination
* @param amount Amount of tokens
Expand Down Expand Up @@ -492,7 +499,7 @@ contract PolygonZkEVMBridgeV2 is
}
} else {
// Claim wETH
WETHToken.mint(destinationAddress, amount);
_claimWrappedAsset(WETHToken, destinationAddress, amount);
}
} else {
// Check if it's gas token
Expand Down Expand Up @@ -536,7 +543,11 @@ contract PolygonZkEVMBridgeV2 is
);

// Mint tokens for the destination address
newWrappedToken.mint(destinationAddress, amount);
_claimWrappedAsset(
newWrappedToken,
destinationAddress,
amount
);

// Create mappings
tokenInfoToWrappedToken[tokenInfoHash] = address(
Expand All @@ -555,7 +566,8 @@ contract PolygonZkEVMBridgeV2 is
);
} else {
// Use the existing wrapped erc20
TokenWrapped(wrappedToken).mint(
_claimWrappedAsset(
TokenWrapped(wrappedToken),
destinationAddress,
amount
);
Expand Down Expand Up @@ -646,7 +658,7 @@ contract PolygonZkEVMBridgeV2 is
);
} else {
// Mint wETH tokens
WETHToken.mint(destinationAddress, amount);
_claimWrappedAsset(WETHToken, destinationAddress, amount);

// Execute message
/* solhint-disable avoid-low-level-calls */
Expand Down Expand Up @@ -730,15 +742,15 @@ contract PolygonZkEVMBridgeV2 is
* @notice Function to activate the emergency state
" Only can be called by the Polygon ZK-EVM in extreme situations
*/
function activateEmergencyState() external onlyRollupManager {
function activateEmergencyState() external virtual onlyRollupManager {
_activateEmergencyState();
}

/**
* @notice Function to deactivate the emergency state
" Only can be called by the Polygon ZK-EVM
*/
function deactivateEmergencyState() external onlyRollupManager {
function deactivateEmergencyState() external virtual onlyRollupManager {
_deactivateEmergencyState();
}

Expand Down Expand Up @@ -895,6 +907,36 @@ contract PolygonZkEVMBridgeV2 is
globalExitRootManager.updateExitRoot(getRoot());
}

/**
* @notice Burn tokens from wrapped token to execute the bridge
* note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain
* @param tokenWrapped Wrapped token to burnt
* @param amount Amount of tokens
*/
function _bridgeWrappedAsset(
TokenWrapped tokenWrapped,
uint256 amount
) internal virtual {
// Burn tokens
tokenWrapped.burn(msg.sender, amount);
}

/**
* @notice Mints tokens from wrapped token to proceed with the claim
* note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain
* @param tokenWrapped Wrapped token to mint
* @param destinationAddress Minted token receiver
* @param amount Amount of tokens
*/
function _claimWrappedAsset(
TokenWrapped tokenWrapped,
address destinationAddress,
uint256 amount
) internal virtual {
// Mint tokens
tokenWrapped.mint(destinationAddress, amount);
}

/**
* @notice Function decode an index into a wordPos and bitPos
* @param index Index
Expand Down
2 changes: 1 addition & 1 deletion contracts/v2/PolygonZkEVMGlobalExitRootV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ contract PolygonZkEVMGlobalExitRootV2 is
* @param newRoot new exit tree root
*/
function updateExitRoot(bytes32 newRoot) external {
// Store storage variables into temporary variables since will be used multiple times
// Store storage variables into temporal variables since will be used multiple times
bytes32 cacheLastRollupExitRoot;
bytes32 cacheLastMainnetExitRoot;

Expand Down
81 changes: 81 additions & 0 deletions contracts/v2/interfaces/IBridgeL2SovereignChains.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: AGPL-3.0

pragma solidity ^0.8.20;
import "../../interfaces/IBasePolygonZkEVMGlobalExitRoot.sol";
import "./IPolygonZkEVMBridgeV2.sol";

interface IBridgeL2SovereignChains is IPolygonZkEVMBridgeV2 {
/**
* @dev Thrown when try to set a zero address to a non valid zero address field
*/
error InvalidZeroAddress();

/**
* @dev Thrown when the origin network is invalid
*/
error OriginNetworkInvalid();

/**
* @dev Thrown when sender is not the bridge manager
* @notice Bridge manager can set custom mapping for any token
*/
error OnlyBridgeManager();

/**
* @dev Thrown when bridge manager address is invalid
*/
error NotValidBridgeManager();

/**
* @dev Thrown when trying to remove a token mapping that has not been updated by a new one
*/
error TokenNotMapped();

/**
* @dev Thrown when trying to migrate a legacy token that is already the current token
*/
error TokenAlreadyUpdated();

/**
* @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params
*/
error InvalidSovereignWETHAddressParams();

/**
* @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params
*/
error InvalidInitializeFunction();

/**
* @dev Thrown when initializing calling a function with invalid arrays length
*/
error InputArraysLengthMismatch();

/**
* @dev Thrown when trying to map a token that is already mapped
*/
error TokenAlreadyMapped();

/**
* @dev Thrown when trying to remove a legacy mapped token that has nor previously been remapped
*/
error TokenNotRemapped();

/**
* @dev Thrown when trying to set a custom wrapper for weth on a gas token network
*/
error WETHRemappingNotSupportedOnGasTokenNetworks();


function initialize(
uint32 _networkID,
address _gasTokenAddress,
uint32 _gasTokenNetwork,
IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager,
address _polygonRollupManager,
bytes memory _gasTokenMetadata,
address _bridgeManager,
address sovereignWETHAddress,
bool _sovereignWETHAddressIsNotMintable
) external;
}
Loading

0 comments on commit 63a89fe

Please sign in to comment.