Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
.yarn

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
Expand Down Expand Up @@ -187,4 +188,4 @@ tags
# and uncomment the following lines
# .pnp.*

# End of https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn
# End of https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn
10 changes: 7 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
## 0.1.0 (2021-12-04)
## 0.1.0 (2021-12-10)

- refactor(bridge): use ArbRetryableTx#getSubmissionPrice ([0de6272](https://github.com/kleros/kleros-v2/commit/0de6272))
- refactor(sdk): rename ([3241d10](https://github.com/kleros/kleros-v2/commit/3241d10))
- feat: add arbitrum L1 bridge and dependencies ([b412772](https://github.com/kleros/kleros-v2/commit/b412772))
- feat: add arbitrum L2 bridge ([457b060](https://github.com/kleros/kleros-v2/commit/457b060))
- feat: modern toolchain setup and simple RNG smart contracts ([17f6a76](https://github.com/kleros/kleros-v2/commit/17f6a76))
- feat(Arbitration): standard update ([ed930de](https://github.com/kleros/kleros-v2/commit/ed930de))
- fix(Arbitrator): memory to calldata ([4770b1f](https://github.com/kleros/kleros-v2/commit/4770b1f))
- fix(IArbitrator): appeals removed from the standard ([02c20ce](https://github.com/kleros/kleros-v2/commit/02c20ce))
- fix(IArbitrator): change name to arbitration cost ([0ba4f29](https://github.com/kleros/kleros-v2/commit/0ba4f29))
- fix(IArbitrator): interface simplification ([e81fb8b](https://github.com/kleros/kleros-v2/commit/e81fb8b))
- fix(IArbitrator): replaced appealCost with fundingStatus ([f189dd9](https://github.com/kleros/kleros-v2/commit/f189dd9))
- feat: modern toolchain setup and simple RNG smart contracts ([17f6a76](https://github.com/kleros/kleros-v2/commit/17f6a76))
- feat(Arbitration): standard update ([ed930de](https://github.com/kleros/kleros-v2/commit/ed930de))
- chore: added GitHub code scanning ([4a70475](https://github.com/kleros/kleros-v2/commit/4a70475))
- chore: added the hardhat config for layer 2 networks, added hardhat-deploy and mocha ([a12ea0e](https://github.com/kleros/kleros-v2/commit/a12ea0e))
- test: added a test for IncrementalNG ([65a996b](https://github.com/kleros/kleros-v2/commit/65a996b))
Expand Down
6 changes: 5 additions & 1 deletion contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
cache
artifacts

## Hardhat typechain bindings/types
typechain
typechain/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that should go before or after the autogenerated section


# Hardhat deploy files
deployments/localhost
deployments/hardhat
Expand Down Expand Up @@ -170,4 +174,4 @@ tags
# .yarn/cache
# .pnp.*

# End of https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn
# End of https://www.toptal.com/developers/gitignore/api/vim,node,visualstudiocode,yarn
2 changes: 1 addition & 1 deletion contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {

const config: HardhatUserConfig = {
solidity: {
version: "0.8.9",
version: "0.8.10",
settings: {
optimizer: {
enabled: true,
Expand Down
58 changes: 58 additions & 0 deletions contracts/src/bridge/arbitrum/L1Bridge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IInbox.sol";
import "./interfaces/IArbRetryableTx.sol";

contract L1Bridge {
address public l2Target;
IInbox public inbox;
IArbRetryableTx constant arbRetryableTx = IArbRetryableTx(address(110));

event RetryableTicketCreated(uint256 indexed ticketId);

constructor(address _l2Target, address _inbox) {
l2Target = _l2Target;
inbox = IInbox(_inbox);
}

/**
* Sends an arbitrary message from one domain to another.
*
* @dev The caller needs to pay some ETH to cover the gas costs
* of the call on L2. Excess ETH that is not used by gas costs will
* be refunded to the `msg.sender` address on L2.
*
* @notice if a user does not desire immediate redemption, they should
* provide a DepositValue of at least CallValue + MaxSubmissionCost.
* If they do desire immediate execution, they should provide a DepositValue
* of at least CallValue + MaxSubmissionCost + (GasPrice x MaxGas).
*
* @param _calldata The L2 encoded message data.
* @param _maxGas Gas limit for immediate L2 execution attempt.
* @param _gasPriceBid L2 Gas price bid for immediate L2 execution attempt.
* @return Unique id to track the message request/transaction.
*/
function sendCrossDomainMessage(
bytes memory _calldata,
uint256 _maxGas,
uint256 _gasPriceBid
) external payable returns (uint256) {
(uint256 baseSubmissionCost, ) = arbRetryableTx.getSubmissionPrice(_calldata.length);

uint256 ticketID = inbox.createRetryableTicket{value: msg.value}(
l2Target,
0,
baseSubmissionCost,
msg.sender,
msg.sender,
_maxGas,
_gasPriceBid,
_calldata
);

emit RetryableTicketCreated(ticketID);
return ticketID;
}
}
29 changes: 29 additions & 0 deletions contracts/src/bridge/arbitrum/L2Bridge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IArbSys.sol";

contract L2Bridge {
address public l1Target;
IArbSys constant arbsys = IArbSys(address(100));

event L2ToL1TxCreated(uint256 indexed withdrawalId);

constructor(address _l1Target) {
l1Target = _l1Target;
}

/**
* Sends an arbitrary message from one domain to another.
*
* @param _calldata The L1 encoded message data.
* @return Unique id to track the message request/transaction.
*/
function sendCrossDomainMessage(bytes memory _calldata) external payable returns (uint256) {
uint256 withdrawalId = arbsys.sendTxToL1(l1Target, _calldata);

emit L2ToL1TxCreated(withdrawalId);
return withdrawalId;
}
}
72 changes: 72 additions & 0 deletions contracts/src/bridge/arbitrum/interfaces/IArbRetryableTx.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
pragma solidity >=0.7.0;

/**
* @title precompiled contract in every Arbitrum chain for retryable transaction related data retrieval and interactions. Exists at 0x000000000000000000000000000000000000006E
*/
interface IArbRetryableTx {
/**
* @notice Redeem a redeemable tx.
* Revert if called by an L2 contract, or if txId does not exist, or if txId reverts.
* If this returns, txId has been completed and is no longer available for redemption.
* If this reverts, txId is still available for redemption (until it times out or is canceled).
@param txId unique identifier of retryable message: keccak256(keccak256(ArbchainId, inbox-sequence-number), uint(0) )
*/
function redeem(bytes32 txId) external;

/**
* @notice Return the minimum lifetime of redeemable txn.
* @return lifetime in seconds
*/
function getLifetime() external view returns (uint256);

/**
* @notice Return the timestamp when ticketId will age out, or zero if ticketId does not exist.
* The timestamp could be in the past, because aged-out tickets might not be discarded immediately.
* @param ticketId unique ticket identifier
* @return timestamp for ticket's deadline
*/
function getTimeout(bytes32 ticketId) external view returns (uint256);

/**
* @notice Return the price, in wei, of submitting a new retryable tx with a given calldata size.
* @param calldataSize call data size to get price of (in wei)
* @return (price, nextUpdateTimestamp). Price is guaranteed not to change until nextUpdateTimestamp.
*/
function getSubmissionPrice(uint256 calldataSize) external view returns (uint256, uint256);

/**
* @notice Return the price, in wei, of extending the lifetime of ticketId by an additional lifetime period. Revert if ticketId doesn't exist.
* @param ticketId unique ticket identifier
* @return (price, nextUpdateTimestamp). Price is guaranteed not to change until nextUpdateTimestamp.
*/
function getKeepalivePrice(bytes32 ticketId) external view returns (uint256, uint256);

/**
@notice Deposits callvalue into the sender's L2 account, then adds one lifetime period to the life of ticketId.
* If successful, emits LifetimeExtended event.
* Revert if ticketId does not exist, or if the timeout of ticketId is already at least one lifetime period in the future, or if the sender has insufficient funds (after the deposit).
* @param ticketId unique ticket identifier
* @return New timeout of ticketId.
*/
function keepalive(bytes32 ticketId) external payable returns (uint256);

/**
* @notice Return the beneficiary of ticketId.
* Revert if ticketId doesn't exist.
* @param ticketId unique ticket identifier
* @return address of beneficiary for ticket
*/
function getBeneficiary(bytes32 ticketId) external view returns (address);

/**
* @notice Cancel ticketId and refund its callvalue to its beneficiary.
* Revert if ticketId doesn't exist, or if called by anyone other than ticketId's beneficiary.
* @param ticketId unique ticket identifier
*/
function cancel(bytes32 ticketId) external;

event TicketCreated(bytes32 indexed ticketId);
event LifetimeExtended(bytes32 indexed ticketId, uint256 newTimeout);
event Redeemed(bytes32 indexed ticketId);
event Canceled(bytes32 indexed ticketId);
}
71 changes: 71 additions & 0 deletions contracts/src/bridge/arbitrum/interfaces/IArbSys.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
pragma solidity >=0.7.0;

/**
* @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality.
*/
interface IArbSys {
/**
* @notice Get internal version number identifying an ArbOS build
* @return version number as int
*/
function arbOSVersion() external pure returns (uint256);

/**
* @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
* @return block number as int
*/
function arbBlockNumber() external view returns (uint256);

/**
* @notice Send given amount of Eth to dest from sender.
* This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1.
* @param destination recipient address on L1
* @return unique identifier for this L2-to-L1 transaction.
*/
function withdrawEth(address destination) external payable returns (uint256);

/**
* @notice Send a transaction to L1
* @param destination recipient address on L1
* @param calldataForL1 (optional) calldata for L1 contract call
* @return a unique identifier for this L2-to-L1 transaction.
*/
function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns (uint256);

/**
* @notice get the number of transactions issued by the given external account or the account sequence number of the given contract
* @param account target account
* @return the number of transactions issued by the given external account or the account sequence number of the given contract
*/
function getTransactionCount(address account) external view returns (uint256);

/**
* @notice get the value of target L2 storage slot
* This function is only callable from address 0 to prevent contracts from being able to call it
* @param account target account
* @param index target index of storage slot
* @return stotage value for the given account at the given index
*/
function getStorageAt(address account, uint256 index) external view returns (uint256);

/**
* @notice check if current call is coming from l1
* @return true if the caller of this was called directly from L1
*/
function isTopLevelCall() external view returns (bool);

event EthWithdrawal(address indexed destAddr, uint256 amount);

event L2ToL1Transaction(
address caller,
address indexed destination,
uint256 indexed uniqueId,
uint256 indexed batchNumber,
uint256 indexInBatch,
uint256 arbBlockNum,
uint256 ethBlockNum,
uint256 timestamp,
uint256 callvalue,
bytes data
);
}
65 changes: 65 additions & 0 deletions contracts/src/bridge/arbitrum/interfaces/IBridge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0

/*
* Copyright 2021, 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.
*/

pragma solidity ^0.8.0;

interface IBridge {
event MessageDelivered(
uint256 indexed messageIndex,
bytes32 indexed beforeInboxAcc,
address inbox,
uint8 kind,
address sender,
bytes32 messageDataHash
);

event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);

event InboxToggle(address indexed inbox, bool enabled);

event OutboxToggle(address indexed outbox, bool enabled);

function deliverMessageToInbox(
uint8 kind,
address sender,
bytes32 messageDataHash
) external payable returns (uint256);

function executeCall(
address destAddr,
uint256 amount,
bytes calldata data
) external returns (bool success, bytes memory returnData);

// These are only callable by the admin
function setInbox(address inbox, bool enabled) external;

function setOutbox(address inbox, bool enabled) external;

// View functions

function activeOutbox() external view returns (address);

function allowedInboxes(address inbox) external view returns (bool);

function allowedOutboxes(address outbox) external view returns (bool);

function inboxAccs(uint256 index) external view returns (bytes32);

function messageCount() external view returns (uint256);
}
Loading