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

Sign up to get free protection for your applications and to get access to all the features.
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