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

Sovereign bridge implementation #330

Open
wants to merge 11 commits into
base: feature/ongoingPP
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ interface IBasePolygonZkEVMGlobalExitRoot {
*/
error OnlyAllowedContracts();

/**
* @dev Thrown when the caller is not the coinbase
*/
error OnlyCoinbase();

function updateExitRoot(bytes32 newRollupExitRoot) external;

function globalExitRootMap(
Expand Down
60 changes: 50 additions & 10 deletions contracts/v2/PolygonZkEVMBridgeV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ contract PolygonZkEVMBridgeV2 is
// WETH address
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 @@ -150,7 +156,7 @@ contract PolygonZkEVMBridgeV2 is
IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager,
address _polygonRollupManager,
bytes memory _gasTokenMetadata
) external virtual initializer {
) public virtual initializer {
networkID = _networkID;
globalExitRootManager = _globalExitRootManager;
polygonRollupManager = _polygonRollupManager;
Expand Down Expand Up @@ -238,7 +244,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 +256,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 +369,7 @@ contract PolygonZkEVMBridgeV2 is
}

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

_bridgeMessage(
destinationNetwork,
Expand Down Expand Up @@ -492,7 +497,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 +541,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 +564,8 @@ contract PolygonZkEVMBridgeV2 is
);
} else {
// Use the existing wrapped erc20
TokenWrapped(wrappedToken).mint(
_claimWrappedAsset(
TokenWrapped(wrappedToken),
destinationAddress,
amount
);
Expand Down Expand Up @@ -608,7 +618,7 @@ contract PolygonZkEVMBridgeV2 is
address destinationAddress,
uint256 amount,
bytes calldata metadata
) external ifNotEmergencyState {
) external virtual ifNotEmergencyState {
// Destination network must be this networkID
if (destinationNetwork != networkID) {
revert DestinationNetworkInvalid();
Expand Down Expand Up @@ -646,7 +656,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 @@ -895,6 +905,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 {
// Burn tokens
tokenWrapped.mint(destinationAddress, amount);
}

/**
* @notice Function decode an index into a wordPos and bitPos
* @param index Index
Expand Down
43 changes: 43 additions & 0 deletions contracts/v2/interfaces/IBridgeL2SovereignChains.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 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 mapped before
*/
error TokenNotMapped();

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