@arbitrum/nitro-contracts 1.0.0 → 1.0.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,8 +5,8 @@ It includes the rollup and fraud proof smart contracts, as well as interfaces fo
5
5
 
6
6
  For more information see https://developer.arbitrum.io/docs/public_nitro_devnet
7
7
 
8
-
9
8
  Compile the contracts locally by running
9
+
10
10
  ```bash
11
11
  git clone https://github.com/offchainlabs/nitro
12
12
  cd nitro/contracts
package/package.json CHANGED
@@ -1,27 +1,25 @@
1
1
  {
2
2
  "name": "@arbitrum/nitro-contracts",
3
- "version": "1.0.0",
3
+ "version": "1.0.2-beta.0",
4
4
  "description": "Layer 2 precompiles and rollup for Arbitrum Nitro",
5
5
  "author": "Offchain Labs, Inc.",
6
6
  "license": "BUSL-1.1",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/offchainlabs/nitro.git",
10
- "directory": "contracts"
9
+ "url": "git+https://github.com/offchainlabs/nitro-contracts.git"
11
10
  },
12
11
  "files": [
13
- "src/",
14
- "scripts/build.bash",
15
- "hardhat.prod-config.js"
12
+ "src/"
16
13
  ],
17
14
  "bugs": {
18
- "url": "https://github.com/offchainlabs/nitro/issues"
15
+ "url": "https://github.com/offchainlabs/nitro-contracts/issues"
19
16
  },
20
17
  "scripts": {
21
- "build": "./scripts/build.bash",
18
+ "build": "hardhat compile",
19
+ "lint:test": "eslint ./test",
22
20
  "solhint": "solhint -f table src/**/*.sol",
23
21
  "prettier:solidity": "prettier --write src/**/*.sol",
24
- "hardhat:prod": "hardhat --config hardhat.prod-config.js",
22
+ "format": "prettier './**/*.{js,json,md,ts,yml,sol}' --write && yarn run lint:test --fix",
25
23
  "build:0.6": "INTERFACE_TESTER_SOLC_VERSION=0.6.9 yarn run build",
26
24
  "build:0.7": "INTERFACE_TESTER_SOLC_VERSION=0.7.0 yarn run build",
27
25
  "test:compatibility": "yarn run build:0.6 && yarn run build:0.7",
@@ -31,7 +29,7 @@
31
29
  "dependencies": {
32
30
  "@openzeppelin/contracts": "4.5.0",
33
31
  "@openzeppelin/contracts-upgradeable": "4.5.2",
34
- "hardhat": "^2.6.6"
32
+ "patch-package": "^6.4.7"
35
33
  },
36
34
  "private": false,
37
35
  "devDependencies": {
@@ -43,12 +41,19 @@
43
41
  "@types/chai": "^4.3.0",
44
42
  "@types/mocha": "^9.0.0",
45
43
  "@types/node": "^17.0.5",
44
+ "@typescript-eslint/eslint-plugin": "^5.14.0",
45
+ "@typescript-eslint/eslint-plugin-tslint": "^5.27.1",
46
+ "@typescript-eslint/parser": "^5.14.0",
46
47
  "chai": "^4.3.4",
48
+ "eslint": "^8.23.1",
49
+ "eslint-config-prettier": "^8.3.0",
50
+ "eslint-plugin-mocha": "^9.0.0",
51
+ "eslint-plugin-prettier": "^4.0.0",
47
52
  "ethereum-waffle": "^3.4.0",
48
53
  "ethers": "^5.5.2",
54
+ "hardhat": "^2.6.6",
49
55
  "hardhat-deploy": "^0.11.4",
50
56
  "hardhat-gas-reporter": "^1.0.8",
51
- "patch-package": "^6.4.7",
52
57
  "postinstall-postinstall": "^2.1.0",
53
58
  "prettier": "^2.5.1",
54
59
  "prettier-plugin-solidity": "^1.0.0-beta.19",
@@ -56,10 +61,11 @@
56
61
  "solhint-plugin-prettier": "^0.0.5",
57
62
  "solidity-coverage": "^0.7.20",
58
63
  "ts-node": "^10.4.0",
64
+ "tslint": "^6.1.3",
59
65
  "typechain": "^8.0.0",
60
66
  "typescript": "^4.5.4"
61
67
  },
62
- "optionalDependencies":{
68
+ "optionalDependencies": {
63
69
  "sol2uml": "2.2.0"
64
70
  }
65
71
  }
@@ -35,7 +35,7 @@ import {
35
35
  L2MessageType_unsignedEOATx,
36
36
  L2MessageType_unsignedContractTx
37
37
  } from "../libraries/MessageTypes.sol";
38
- import {MAX_DATA_SIZE} from "../libraries/Constants.sol";
38
+ import {MAX_DATA_SIZE, UNISWAP_L1_TIMELOCK, UNISWAP_L2_FACTORY} from "../libraries/Constants.sol";
39
39
  import "../precompiles/ArbSys.sol";
40
40
 
41
41
  import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
@@ -527,6 +527,84 @@ contract Inbox is DelegateCallAware, PausableUpgradeable, IInbox {
527
527
  );
528
528
  }
529
529
 
530
+ /// @notice This is an one-time-exception to resolve a misconfiguration of Uniswap Arbitrum deployment
531
+ /// Only the Uniswap L1 Timelock may call this function and it is allowed to create a crosschain
532
+ /// retryable ticket without address aliasing. More info here:
533
+ /// https://gov.uniswap.org/t/consensus-check-fix-the-cross-chain-messaging-bridge-on-arbitrum/18547
534
+ /// @dev This function will be removed in future releases
535
+ function uniswapCreateRetryableTicket(
536
+ address to,
537
+ uint256 l2CallValue,
538
+ uint256 maxSubmissionCost,
539
+ address excessFeeRefundAddress,
540
+ address callValueRefundAddress,
541
+ uint256 gasLimit,
542
+ uint256 maxFeePerGas,
543
+ bytes calldata data
544
+ ) external payable whenNotPaused onlyAllowed returns (uint256) {
545
+ // this can only be called by UNISWAP_L1_TIMELOCK
546
+ require(msg.sender == UNISWAP_L1_TIMELOCK, "NOT_UNISWAP_L1_TIMELOCK");
547
+ // the retryable can only call UNISWAP_L2_FACTORY
548
+ require(to == UNISWAP_L2_FACTORY, "NOT_TO_UNISWAP_L2_FACTORY");
549
+
550
+ // ensure the user's deposit alone will make submission succeed
551
+ if (msg.value < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
552
+ revert InsufficientValue(
553
+ maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas,
554
+ msg.value
555
+ );
556
+ }
557
+
558
+ // if a refund address is a contract, we apply the alias to it
559
+ // so that it can access its funds on the L2
560
+ // since the beneficiary and other refund addresses don't get rewritten by arb-os
561
+ if (AddressUpgradeable.isContract(excessFeeRefundAddress)) {
562
+ excessFeeRefundAddress = AddressAliasHelper.applyL1ToL2Alias(excessFeeRefundAddress);
563
+ }
564
+ if (AddressUpgradeable.isContract(callValueRefundAddress)) {
565
+ // this is the beneficiary. be careful since this is the address that can cancel the retryable in the L2
566
+ callValueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(callValueRefundAddress);
567
+ }
568
+
569
+ // gas price and limit of 1 should never be a valid input, so instead they are used as
570
+ // magic values to trigger a revert in eth calls that surface data without requiring a tx trace
571
+ if (gasLimit == 1 || maxFeePerGas == 1)
572
+ revert RetryableData(
573
+ msg.sender,
574
+ to,
575
+ l2CallValue,
576
+ msg.value,
577
+ maxSubmissionCost,
578
+ excessFeeRefundAddress,
579
+ callValueRefundAddress,
580
+ gasLimit,
581
+ maxFeePerGas,
582
+ data
583
+ );
584
+
585
+ uint256 submissionFee = calculateRetryableSubmissionFee(data.length, block.basefee);
586
+ if (maxSubmissionCost < submissionFee)
587
+ revert InsufficientSubmissionCost(submissionFee, maxSubmissionCost);
588
+
589
+ return
590
+ _deliverMessage(
591
+ L1MessageType_submitRetryableTx,
592
+ AddressAliasHelper.undoL1ToL2Alias(msg.sender),
593
+ abi.encodePacked(
594
+ uint256(uint160(to)),
595
+ l2CallValue,
596
+ msg.value,
597
+ maxSubmissionCost,
598
+ uint256(uint160(excessFeeRefundAddress)),
599
+ uint256(uint160(callValueRefundAddress)),
600
+ gasLimit,
601
+ maxFeePerGas,
602
+ data.length,
603
+ data
604
+ )
605
+ );
606
+ }
607
+
530
608
  function _deliverMessage(
531
609
  uint8 _kind,
532
610
  address _sender,
@@ -285,7 +285,7 @@ contract ChallengeManager is DelegateCallAware, IChallengeManager {
285
285
  return challenges[challengeIndex].current.addr;
286
286
  }
287
287
 
288
- function isTimedOut(uint64 challengeIndex) public view override returns (bool) {
288
+ function isTimedOut(uint64 challengeIndex) public view virtual override returns (bool) {
289
289
  return challenges[challengeIndex].isTimedOut();
290
290
  }
291
291
 
@@ -11,3 +11,6 @@ uint64 constant NO_CHAL_INDEX = 0;
11
11
 
12
12
  // Expected seconds per block in Ethereum PoS
13
13
  uint256 constant ETH_POS_BLOCK_TIME = 12;
14
+
15
+ address constant UNISWAP_L1_TIMELOCK = 0x1a9C8182C09F50C8318d769245beA52c32BE35BC;
16
+ address constant UNISWAP_L2_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
@@ -151,7 +151,7 @@ contract InboxStub is IInbox {
151
151
  address,
152
152
  uint256,
153
153
  bytes calldata
154
- ) external returns (uint256) {
154
+ ) external pure returns (uint256) {
155
155
  revert("NOT_IMPLEMENTED");
156
156
  }
157
157
 
@@ -161,7 +161,7 @@ contract InboxStub is IInbox {
161
161
  uint256,
162
162
  uint256,
163
163
  address
164
- ) external returns (uint256) {
164
+ ) external pure returns (uint256) {
165
165
  revert("NOT_IMPLEMENTED");
166
166
  }
167
167
 
@@ -0,0 +1,9 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
8
+
9
+ contract ProxyAdminForBinding is ProxyAdmin {}
@@ -13,11 +13,17 @@ contract Simple {
13
13
  event CounterEvent(uint64 count);
14
14
  event RedeemedEvent(address caller, address redeemer);
15
15
  event NullEvent();
16
+ event LogAndIncrementCalled(uint256 expected, uint256 have);
16
17
 
17
18
  function increment() external {
18
19
  counter++;
19
20
  }
20
21
 
22
+ function logAndIncrement(uint256 expected) external {
23
+ emit LogAndIncrementCalled(expected, counter);
24
+ counter++;
25
+ }
26
+
21
27
  function incrementEmit() external {
22
28
  counter++;
23
29
  emit CounterEvent(counter);
@@ -104,4 +110,12 @@ contract Simple {
104
110
  (success, ) = address(this).call(data);
105
111
  require(success, "CALL_FAILED");
106
112
  }
113
+
114
+ function checkGasUsed(address to, bytes calldata input) external view returns (uint256) {
115
+ uint256 before = gasleft();
116
+ // The inner call may revert, but we still want to return the amount of gas used,
117
+ // so we ignore the result of this call.
118
+ (to.staticcall{gas: before - 10000}(input));
119
+ return before - gasleft();
120
+ }
107
121
  }
@@ -0,0 +1,13 @@
1
+ // Copyright 2021-2022, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/nitro/blob/master/LICENSE
3
+ // SPDX-License-Identifier: BUSL-1.1
4
+
5
+ pragma solidity ^0.8.0;
6
+
7
+ import "../challenge/ChallengeManager.sol";
8
+
9
+ contract TimedOutChallengeManager is ChallengeManager {
10
+ function isTimedOut(uint64) public pure override returns (bool) {
11
+ return true;
12
+ }
13
+ }
@@ -1,5 +1,5 @@
1
- // Copyright 2021-2022, Offchain Labs, Inc.
2
- // For license information, see https://github.com/nitro/blob/master/LICENSE
1
+ // Copyright 2021-2023, Offchain Labs, Inc.
2
+ // For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE
3
3
  // SPDX-License-Identifier: BUSL-1.1
4
4
 
5
5
  pragma solidity >=0.4.21 <0.9.0;
@@ -15,6 +15,9 @@ interface ArbDebug {
15
15
  /// @notice Emit events with values based on the args provided
16
16
  function events(bool flag, bytes32 value) external payable returns (address, uint256);
17
17
 
18
+ /// @notice Tries (and fails) to emit logs in a view context
19
+ function eventsView() external view;
20
+
18
21
  // Events that exist for testing log creation and pricing
19
22
  event Basic(bool flag, bytes32 indexed value);
20
23
  event Mixed(
@@ -34,6 +37,8 @@ interface ArbDebug {
34
37
 
35
38
  function customRevert(uint64 number) external pure;
36
39
 
40
+ function legacyError() external pure;
41
+
37
42
  error Custom(uint64, string, bool);
38
43
  error Unused();
39
44
  }
@@ -147,4 +147,6 @@ interface ArbSys {
147
147
  bytes32 indexed hash,
148
148
  uint256 indexed position
149
149
  );
150
+
151
+ error InvalidBlockNumber(uint256 requested, uint256 current);
150
152
  }
@@ -1,18 +0,0 @@
1
- /**
2
- * @type import('hardhat/config').HardhatUserConfig
3
- */
4
- module.exports = {
5
- solidity: {
6
- version: "0.8.9",
7
- settings: {
8
- optimizer: {
9
- enabled: true,
10
- runs: 100,
11
- },
12
- },
13
- },
14
- paths: {
15
- sources: "./src",
16
- artifacts: "build/contracts",
17
- },
18
- };
@@ -1,5 +0,0 @@
1
- #!/bin/bash
2
- if [[ $PWD == */contracts ]];
3
- then $npm_execpath run hardhat compile;
4
- else $npm_execpath run hardhat:prod compile;
5
- fi