Skip to content

Commit

Permalink
Merge pull request #5 from darcys22/custom-bridge
Browse files Browse the repository at this point in the history
start of custom bridge
  • Loading branch information
darcys22 authored Mar 4, 2025
2 parents 70a2a9f + aa6bc46 commit 656e6cc
Show file tree
Hide file tree
Showing 9 changed files with 606 additions and 205 deletions.
59 changes: 55 additions & 4 deletions contracts/SESH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,72 @@ pragma solidity ^0.8.26;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import "./libraries/arbitrum-bridge/ICustomToken.sol";
import "./libraries/arbitrum-bridge/IGateways.sol";
import "./libraries/Shared.sol";

/**
* @title SESH contract
* @notice The SESH utility token
* @notice The SESH utility token with Arbitrum Custom Gateway support
*/
contract SESH is ERC20, ERC20Permit, Shared {
contract SESH is ICustomToken, ERC20, ERC20Permit, Shared {
address public immutable gateway;
address public immutable router;
bool private shouldRegisterGateway;

constructor(
uint256 totalSupply_,
address receiverGenesisAddress
) ERC20("Session Token", "SESH") ERC20Permit("Session Token") nzAddr(receiverGenesisAddress) nzUint(totalSupply_) {
address receiverGenesisAddress,
address _gateway,
address _router
) ERC20("Session Token", "SESH") ERC20Permit("Session Token") nzAddr(receiverGenesisAddress) nzUint(totalSupply_) {
_mint(receiverGenesisAddress, totalSupply_);
gateway = _gateway;
router = _router;
}

function decimals() public pure override returns (uint8) {
return 9;
}

/// @notice Returns `0xb1` to indicate the token is Arbitrum enabled
function isArbitrumEnabled() external view override returns (uint8) {
require(shouldRegisterGateway, "NOT_EXPECTED_CALL");
return uint8(0xb1);
}

/// @notice Register token on L2 via the Arbitrum Custom Gateway
function registerTokenOnL2(
address l2CustomTokenAddress,
uint256 maxSubmissionCostForCustomGateway,
uint256 maxSubmissionCostForRouter,
uint256 maxGasForCustomGateway,
uint256 maxGasForRouter,
uint256 gasPriceBid,
uint256 valueForGateway,
uint256 valueForRouter,
address creditBackAddress
) public payable override {
bool prev = shouldRegisterGateway;
shouldRegisterGateway = true;

IL1CustomGateway(gateway).registerTokenToL2{ value: valueForGateway }(
l2CustomTokenAddress,
maxGasForCustomGateway,
gasPriceBid,
maxSubmissionCostForCustomGateway,
creditBackAddress
);

IL2GatewayRouter(router).setGateway{ value: valueForRouter }(
gateway,
maxGasForRouter,
gasPriceBid,
maxSubmissionCostForRouter,
creditBackAddress
);

shouldRegisterGateway = prev;
}
}

60 changes: 60 additions & 0 deletions contracts/SESHL2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "./libraries/arbitrum-bridge/IArbToken.sol";

/**
* @title SESHL2 Token
* @notice L2 representation of the SESH token, bridged from L1
*/
contract SESHL2 is Initializable, ERC20Upgradeable, IArbToken {
address public l2Gateway;
address public l1Address;

modifier onlyL2Gateway() {
require(msg.sender == l2Gateway, "NOT_GATEWAY");
_;
}

/**
* @notice Initializes the L2 token with the same name, symbol, and decimals as L1.
* @param l2Gateway_ The L2 gateway that interacts with the Arbitrum bridge.
* @param l1Address_ The corresponding L1 token address.
*/
function initialize(address l2Gateway_, address l1Address_) public initializer {
// Initialize state variables.
l2Gateway = l2Gateway_;
l1Address = l1Address_;

// Initialize ERC20 with token name and symbol.
__ERC20_init("Session Token", "SESH");
}

/**
* @notice Returns the number of decimals used to get its user representation.
* @return The number of decimals (9)
*/
function decimals() public pure override returns (uint8) {
return 9;
}

/**
* @notice Increases the token supply by minting tokens.
* @param account The account that will receive the minted tokens.
* @param amount The amount of tokens to mint.
*/
function bridgeMint(address account, uint256 amount) external override onlyL2Gateway {
_mint(account, amount);
}

/**
* @notice Decreases the token supply by burning tokens.
* @param account The account whose tokens will be burned.
* @param amount The amount of tokens to burn.
*/
function bridgeBurn(address account, uint256 amount) external override onlyL2Gateway {
_burn(account, amount);
}
}
44 changes: 44 additions & 0 deletions contracts/libraries/arbitrum-bridge/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);
}
55 changes: 55 additions & 0 deletions contracts/libraries/arbitrum-bridge/ICustomToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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.
*/

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

interface ArbitrumEnabledToken {
/// @notice should return `0xb1` if token is enabled for arbitrum gateways
/// @dev Previous implmentation used to return `uint8(0xa4b1)`, however that causes compile time error in Solidity 0.8. due to type mismatch.
/// In current version `uint8(0xb1)` shall be returned, which results in no change as that's the same value as truncated `uint8(0xa4b1)`.
function isArbitrumEnabled() external view returns (uint8);
}

/**
* @title Minimum expected interface for L1 custom token (see TestCustomTokenL1.sol for an example implementation)
*/
interface ICustomToken is ArbitrumEnabledToken {
/**
* @notice Should make an external call to EthERC20Bridge.registerCustomL2Token
*/
function registerTokenOnL2(
address l2CustomTokenAddress,
uint256 maxSubmissionCostForCustomBridge,
uint256 maxSubmissionCostForRouter,
uint256 maxGasForCustomBridge,
uint256 maxGasForRouter,
uint256 gasPriceBid,
uint256 valueForGateway,
uint256 valueForRouter,
address creditBackAddress
) external payable;
}

interface L1MintableToken is ICustomToken {
function bridgeMint(address account, uint256 amount) external;
}

interface L1ReverseToken is L1MintableToken {
function bridgeBurn(address account, uint256 amount) external;
}
23 changes: 23 additions & 0 deletions contracts/libraries/arbitrum-bridge/IGateways.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IL1CustomGateway {
function registerTokenToL2(
address _l2Address,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256);
}

interface IL2GatewayRouter {
function setGateway(
address _gateway,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256);
}

Loading

0 comments on commit 656e6cc

Please sign in to comment.