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

arb bridge contracts #583

Merged
merged 13 commits into from
Jul 22, 2024
4 changes: 3 additions & 1 deletion .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
node-version: [14.x]
node-version: [20.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
Expand All @@ -31,6 +31,8 @@ jobs:
- name: JS Lint
run: |
npx eslint .
- name: Solidity Compile
run: npm run clean && npm run compile
- name: Solidity Tests # Needed because coverage doesn't work with all tests
run: npm run test
- name: Solidity Test Coverage
Expand Down
2 changes: 1 addition & 1 deletion .solhintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
contracts/mocks
contracts/HATToken.sol
contracts/token/HATToken.sol
2 changes: 1 addition & 1 deletion contracts/mocks/HATTokenMock.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "../HATToken.sol";
import "../token/HATToken.sol";
//solhint-disable func-visibility
//solhint-disable no-empty-blocks

Expand Down
17 changes: 17 additions & 0 deletions contracts/mocks/MockL1CustomGateway.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "../token/HATTokenArbitrumBridgeL1.sol";

contract MockL1CustomGateway {
function registerTokenToL2(
address _l2Address,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256) {
require(HATTokenArbitrumBridgeL1(msg.sender).isArbitrumEnabled() == uint8(0xb1), "Failed to verify");
return 1;
}
}
15 changes: 15 additions & 0 deletions contracts/mocks/MockL2GatewayRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;


contract MockL2GatewayRouter {
function setGateway(
address _gateway,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256) {
return 1;
}
}
2 changes: 1 addition & 1 deletion contracts/HATToken.sol → contracts/token/HATToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IHATToken.sol";
import "../interfaces/IHATToken.sol";

contract HATToken is IHATToken, ERC20Votes, ERC20Capped, Ownable {

Expand Down
93 changes: 93 additions & 0 deletions contracts/token/HATTokenArbitrumBridgeL1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "./HATToken.sol";
import "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/ICustomToken.sol";

/**
* @title Interface needed to call function registerTokenToL2 of the L1CustomGateway
*/
interface IL1CustomGateway {
function registerTokenToL2(
address _l2Address,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256);
}

/**
* @title Interface needed to call function setGateway of the L2GatewayRouter
*/
interface IL2GatewayRouter {
function setGateway(
address _gateway,
uint256 _maxGas,
uint256 _gasPriceBid,
uint256 _maxSubmissionCost,
address _creditBackAddress
) external payable returns (uint256);
}

contract HATTokenArbitrumBridgeL1 is ICustomToken, HATToken {
address private customGatewayAddress;
address private routerAddress;
bool private shouldRegisterGateway;

constructor (address _customGatewayAddress, address _routerAddress, address _governance) HATToken(_governance) {
customGatewayAddress = _customGatewayAddress;
routerAddress = _routerAddress;
}

function isArbitrumEnabled() external view override returns (uint8) {
require(shouldRegisterGateway, "NOT_EXPECTED_CALL");
return uint8(0xb1);
}

function registerTokenOnL2(
address l2CustomTokenAddress,
uint256 maxSubmissionCostForCustomGateway,
uint256 maxSubmissionCostForRouter,
uint256 maxGasForCustomGateway,
uint256 maxGasForRouter,
uint256 gasPriceBid,
uint256 valueForGateway,
uint256 valueForRouter,
address creditBackAddress
) public override payable onlyOwner {
// we temporarily set `shouldRegisterGateway` to true for the callback in registerTokenToL2 to succeed
bool prev = shouldRegisterGateway;
shouldRegisterGateway = true;

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

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

shouldRegisterGateway = prev;
}

function transferFrom(
address sender,
address recipient,
uint256 amount
) public override(ICustomToken, ERC20) returns (bool) {
return super.transferFrom(sender, recipient, amount);
}

function balanceOf(address account) public view override(ICustomToken, ERC20) returns (uint256) {
return super.balanceOf(account);
}
}
36 changes: 36 additions & 0 deletions contracts/token/HATTokenArbitrumBridgeL2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "./HATToken.sol";
import "@arbitrum/token-bridge-contracts/contracts/tokenbridge/arbitrum/IArbToken.sol";

contract HATTokenArbitrumBridgeL2 is HATToken, IArbToken {
address public l2Gateway;
address public override l1Address;

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

constructor(address _l2Gateway, address _l1TokenAddress) HATToken(address(0)) {
l2Gateway = _l2Gateway;
l1Address = _l1TokenAddress;
transferable = true;
emit TransferableSet();
}

/**
* @notice should increase token supply by amount, and should only be callable by the L2Gateway.
*/
function bridgeMint(address account, uint256 amount) external override onlyL2Gateway {
_mint(account, amount);
}

/**
* @notice should decrease token supply by amount, and should only be callable by the L2Gateway.
*/
function bridgeBurn(address account, uint256 amount) external override onlyL2Gateway {
_burn(account, amount);
}
}
2 changes: 1 addition & 1 deletion contracts/tokenlock/HATTokenLock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.16;

import "./TokenLock.sol";
import "../HATToken.sol";
import "../token/HATToken.sol";


contract HATTokenLock is TokenLock {
Expand Down
41 changes: 41 additions & 0 deletions docs/dodoc/mocks/MockL1CustomGateway.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# MockL1CustomGateway









## Methods

### registerTokenToL2

```solidity
function registerTokenToL2(address _l2Address, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress) external payable returns (uint256)
```





#### Parameters

| Name | Type | Description |
|---|---|---|
| _l2Address | address | undefined |
| _maxGas | uint256 | undefined |
| _gasPriceBid | uint256 | undefined |
| _maxSubmissionCost | uint256 | undefined |
| _creditBackAddress | address | undefined |

#### Returns

| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |




41 changes: 41 additions & 0 deletions docs/dodoc/mocks/MockL2GatewayRouter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# MockL2GatewayRouter









## Methods

### setGateway

```solidity
function setGateway(address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress) external payable returns (uint256)
```





#### Parameters

| Name | Type | Description |
|---|---|---|
| _gateway | address | undefined |
| _maxGas | uint256 | undefined |
| _gasPriceBid | uint256 | undefined |
| _maxSubmissionCost | uint256 | undefined |
| _creditBackAddress | address | undefined |

#### Returns

| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined |




Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# IArbToken









## Methods

### bridgeBurn

```solidity
function bridgeBurn(address account, uint256 amount) external nonpayable
```

should decrease token supply by amount, and should (probably) only be callable by the L1 bridge.



#### Parameters

| Name | Type | Description |
|---|---|---|
| account | address | undefined |
| amount | uint256 | undefined |

### bridgeMint

```solidity
function bridgeMint(address account, uint256 amount) external nonpayable
```

should increase token supply by amount, and should (probably) only be callable by the L1 bridge.



#### Parameters

| Name | Type | Description |
|---|---|---|
| account | address | undefined |
| amount | uint256 | undefined |

### l1Address

```solidity
function l1Address() external view returns (address)
```






#### Returns

| Name | Type | Description |
|---|---|---|
| _0 | address | address of layer 1 token |




Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ArbitrumEnabledToken









## Methods

### isArbitrumEnabled

```solidity
function isArbitrumEnabled() external view returns (uint8)
```

should return `0xb1` if token is enabled for arbitrum gateways

*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)`.*


#### Returns

| Name | Type | Description |
|---|---|---|
| _0 | uint8 | undefined |




Loading
Loading