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

(feat) Remove zilbridge escape for future mint and burn tokens. #28

Merged
merged 2 commits into from
Jan 29, 2025
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
56 changes: 56 additions & 0 deletions smart-contracts/contracts/periphery/BridgedTokenV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BridgedTokenV2 is ERC20, ERC20Burnable, Ownable {
uint8 private immutable _decimals;

constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) ERC20(name_, symbol_) Ownable(_msgSender()) {
_decimals = decimals_;
}

function decimals() public view override returns (uint8) {
return _decimals;
}

function circulatingSupply() external view returns (uint256 amount) {
rrw-zilliqa marked this conversation as resolved.
Show resolved Hide resolved
return totalSupply();
}

function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}

function burn(uint256 value) public override onlyOwner {
super.burn(value);
}

function burnFrom(
address account,
uint256 value
) public override onlyOwner {
super.burnFrom(account, value);
}

function transfer(
address to,
uint256 value
) public override returns (bool) {
return super.transfer(to, value);
}

function transferFrom(
address from,
address to,
uint256 value
) public override returns (bool) {
return super.transferFrom(from, to, value);
}
}
52 changes: 52 additions & 0 deletions smart-contracts/contracts/periphery/BridgedTokenV3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BridgedTokenV3 is ERC20, ERC20Burnable, Ownable {
uint8 private immutable _decimals;

constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) ERC20(name_, symbol_) Ownable(_msgSender()) {
_decimals = decimals_;
}

function decimals() public view override returns (uint8) {
return _decimals;
}

function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}

function burn(uint256 value) public override onlyOwner {
super.burn(value);
}

function burnFrom(
address account,
uint256 value
) public override onlyOwner {
super.burnFrom(account, value);
}

function transfer(
address to,
uint256 value
) public override returns (bool) {
return super.transfer(to, value);
}

function transferFrom(
address from,
address to,
uint256 value
) public override returns (bool) {
return super.transferFrom(from, to, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.20;

import {TokenManagerUpgradeableV4, ITokenManager} from "contracts/periphery/TokenManagerV4/TokenManagerUpgradeableV4.sol";
import {BridgedTokenV2} from "contracts/periphery/BridgedTokenV2.sol";

interface IMintAndBurnTokenManager {
event Minted(address indexed token, address indexed recipient, uint amount);
event Burned(address indexed token, address indexed from, uint amount);
event BridgedTokenDeployed(
address token,
address remoteToken,
address remoteTokenManager,
uint remoteChainId
);
}

contract MintAndBurnTokenManagerUpgradeableV5 is
IMintAndBurnTokenManager,
TokenManagerUpgradeableV4
{
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function deployToken(
string calldata name,
string calldata symbol,
uint8 decimals,
address remoteToken,
address tokenManager,
uint remoteChainId
) external returns (BridgedTokenV2) {
return
_deployToken(
name,
symbol,
decimals,
remoteToken,
tokenManager,
remoteChainId
);
}

function deployToken(
string calldata name,
string calldata symbol,
address remoteToken,
address tokenManager,
uint remoteChainId
) external returns (BridgedTokenV2) {
return
_deployToken(
name,
symbol,
18,
remoteToken,
tokenManager,
remoteChainId
);
}

function _deployToken(
string calldata name,
string calldata symbol,
uint8 decimals,
address remoteToken,
address tokenManager,
uint remoteChainId
) internal onlyOwner returns (BridgedTokenV2) {
// TODO: deployed counterfactually
BridgedTokenV2 bridgedToken = new BridgedTokenV2(name, symbol, decimals);
RemoteToken memory remoteTokenStruct = RemoteToken(
remoteToken,
tokenManager,
remoteChainId
);

_registerToken(address(bridgedToken), remoteTokenStruct);

emit BridgedTokenDeployed(
address(bridgedToken),
remoteToken,
tokenManager,
remoteChainId
);

return bridgedToken;
}

function transferTokenOwnership(
address localToken,
uint remoteChainId,
address newOwner
) external onlyOwner {
BridgedTokenV2(localToken).transferOwnership(newOwner);
_removeToken(localToken, remoteChainId);
}

// Outgoing
function _handleTransfer(
address token,
address from,
uint amount
) internal override {
BridgedTokenV2(token).burnFrom(from, amount);
emit Burned(token, from, amount);
}

// Incoming
function _handleAccept(
address token,
address recipient,
uint amount
) internal override {
BridgedTokenV2(token).mint(recipient, amount);
emit Minted(token, recipient, amount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.20;

import {TokenManagerUpgradeableV4, ITokenManager} from "contracts/periphery/TokenManagerV4/TokenManagerUpgradeableV4.sol";
import {BridgedTokenV3} from "contracts/periphery/BridgedTokenV3.sol";

interface IMintAndBurnTokenManager {
event Minted(address indexed token, address indexed recipient, uint amount);
event Burned(address indexed token, address indexed from, uint amount);
event BridgedTokenDeployed(
address token,
address remoteToken,
address remoteTokenManager,
uint remoteChainId
);
}

contract MintAndBurnTokenManagerUpgradeableV6 is
IMintAndBurnTokenManager,
TokenManagerUpgradeableV4
{
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function deployToken(
string calldata name,
string calldata symbol,
uint8 decimals,
address remoteToken,
address tokenManager,
uint remoteChainId
) external returns (BridgedTokenV3) {
return
_deployToken(
name,
symbol,
decimals,
remoteToken,
tokenManager,
remoteChainId
);
}

function deployToken(
string calldata name,
string calldata symbol,
address remoteToken,
address tokenManager,
uint remoteChainId
) external returns (BridgedTokenV3) {
return
_deployToken(
name,
symbol,
18,
remoteToken,
tokenManager,
remoteChainId
);
}

function _deployToken(
string calldata name,
string calldata symbol,
uint8 decimals,
address remoteToken,
address tokenManager,
uint remoteChainId
) internal onlyOwner returns (BridgedTokenV3) {
// TODO: deployed counterfactually
BridgedTokenV3 bridgedToken = new BridgedTokenV3(name, symbol, decimals);
RemoteToken memory remoteTokenStruct = RemoteToken(
remoteToken,
tokenManager,
remoteChainId
);

_registerToken(address(bridgedToken), remoteTokenStruct);

emit BridgedTokenDeployed(
address(bridgedToken),
remoteToken,
tokenManager,
remoteChainId
);

return bridgedToken;
}

function transferTokenOwnership(
address localToken,
uint remoteChainId,
address newOwner
) external onlyOwner {
BridgedTokenV3(localToken).transferOwnership(newOwner);
_removeToken(localToken, remoteChainId);
}

// Outgoing
function _handleTransfer(
address token,
address from,
uint amount
) internal override {
BridgedTokenV3(token).burnFrom(from, amount);
emit Burned(token, from, amount);
}

// Incoming
function _handleAccept(
address token,
address recipient,
uint amount
) internal override {
BridgedTokenV3(token).mint(recipient, amount);
emit Minted(token, recipient, amount);
}
}
8 changes: 4 additions & 4 deletions smart-contracts/test/periphery/TokenBridge.integration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ pragma solidity 0.8.20;
import {Tester, Vm} from "test/Tester.sol";
import {ITokenManagerStructs, TokenManagerUpgradeable} from "contracts/periphery/TokenManagerUpgradeable.sol";
import {LockAndReleaseOrNativeTokenManagerUpgradeableV5} from "contracts/periphery/TokenManagerV5/LockAndReleaseOrNativeTokenManagerUpgradeableV5.sol";
import {MintAndBurnTokenManagerUpgradeableV4} from "contracts/periphery/TokenManagerV4/MintAndBurnTokenManagerUpgradeableV4.sol";
import {BridgedToken} from "contracts/periphery/BridgedToken.sol";
import {MintAndBurnTokenManagerUpgradeableV6} from "contracts/periphery/TokenManagerV6/MintAndBurnTokenManagerUpgradeableV6.sol";
import {BridgedTokenV3} from "contracts/periphery/BridgedTokenV3.sol";
import {CallMetadata, IRelayerEvents} from "contracts/core/Relayer.sol";
import {ValidatorManager} from "contracts/core/ValidatorManager.sol";
import {ChainGateway} from "contracts/core/ChainGateway.sol";
Expand Down Expand Up @@ -37,8 +37,8 @@ contract TokenBridgeIntegrationTests is
ChainGateway sourceChainGateway;
ValidatorManager sourceValidatorManager;

MintAndBurnTokenManagerUpgradeableV4 remoteTokenManager;
BridgedToken bridgedToken;
MintAndBurnTokenManagerUpgradeableV6 remoteTokenManager;
BridgedTokenV3 bridgedToken;
ChainGateway remoteChainGateway;
ValidatorManager remoteValidatorManager;

Expand Down
8 changes: 4 additions & 4 deletions smart-contracts/test/periphery/TokenBridge.native.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {ITokenManagerStructs, TokenManagerUpgradeable} from "contracts/periphery
import {LockAndReleaseOrNativeTokenManagerUpgradeableV3} from "contracts/periphery/TokenManagerV3/LockAndReleaseOrNativeTokenManagerUpgradeableV3.sol";
import {LockAndReleaseOrNativeTokenManagerUpgradeableV5} from "contracts/periphery/TokenManagerV5/LockAndReleaseOrNativeTokenManagerUpgradeableV5.sol";
import {MintAndBurnTokenManagerUpgradeableV3} from "contracts/periphery/TokenManagerV3/MintAndBurnTokenManagerUpgradeableV3.sol";
import {MintAndBurnTokenManagerUpgradeableV4} from "contracts/periphery/TokenManagerV4/MintAndBurnTokenManagerUpgradeableV4.sol";
import {BridgedToken} from "contracts/periphery/BridgedToken.sol";
import {MintAndBurnTokenManagerUpgradeableV6} from "contracts/periphery/TokenManagerV6/MintAndBurnTokenManagerUpgradeableV6.sol";
import {BridgedTokenV3} from "contracts/periphery/BridgedTokenV3.sol";
import {CallMetadata, IRelayerEvents} from "contracts/core/Relayer.sol";
import {ValidatorManager} from "contracts/core/ValidatorManager.sol";
import {ChainGateway} from "contracts/core/ChainGateway.sol";
Expand Down Expand Up @@ -39,8 +39,8 @@ contract TokenBridgeNativeTests is
ChainGateway sourceChainGateway;
ValidatorManager sourceValidatorManager;

MintAndBurnTokenManagerUpgradeableV4 remoteTokenManager;
BridgedToken bridgedToken;
MintAndBurnTokenManagerUpgradeableV6 remoteTokenManager;
BridgedTokenV3 bridgedToken;
ChainGateway remoteChainGateway;
ValidatorManager remoteValidatorManager;

Expand Down
Loading
Loading