Skip to content

Commit 5052476

Browse files
authored
Merge pull request #40 from OffchainLabs/add-storage-check
feat: add storage layout check
2 parents abf3d6b + cce2f9a commit 5052476

16 files changed

+713
-275
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- run: |
1515
yarn install
1616
yarn build
17+
yarn test:storage
1718
yarn test
1819
1920
workflows:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ cache
55
build
66
artifacts
77
deployment.json
8+
test/storage/*-old.dot

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
"lint": "yarn lint:solidity && yarn lint:js",
1414
"format": "prettier './**/*.{js,json,md,ts,yml,sol}' --write && yarn lint --fix",
1515
"test:compatibility": "yarn run build:0.6 && yarn run build:0.7 && yarn run build:0.8",
16-
"test": "hardhat test test/*",
16+
"test": "hardhat test test/*.ts",
1717
"test:e2e": "hardhat test test/*.e2e.ts",
1818
"test:l1": "hardhat test test/*.l1.ts",
1919
"test:l2": "hardhat test test/*.l2.ts",
20+
"test:storage": "./scripts/storage_layout_test.bash",
2021
"typechain": "hardhat typechain",
2122
"deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet",
2223
"gen:uml": "sol2uml ./contracts/tokenbridge/arbitrum,./contracts/tokenbridge/ethereum,./contracts/tokenbridge/libraries -o ./gatewayUML.svg",
@@ -62,7 +63,7 @@
6263
"prettier": "^2.3.2",
6364
"prettier-plugin-solidity": "^1.0.0-beta.17",
6465
"prompts": "^2.4.1",
65-
"sol2uml": "^1.1.29",
66+
"sol2uml": "^2.5.4",
6667
"solhint": "^3.2.0",
6768
"solhint-plugin-prettier": "^0.0.5",
6869
"solidity-coverage": "v0.7.17",

scripts/storage_layout_test.bash

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
output_dir="./test/storage"
3+
for CONTRACTNAME in L1ERC20Gateway L1CustomGateway L1ReverseCustomGateway L1WethGateway L2ERC20Gateway L2CustomGateway L2ReverseCustomGateway L2WethGateway L1GatewayRouter L2GatewayRouter StandardArbERC20
4+
do
5+
echo "Checking storage change of $CONTRACTNAME"
6+
[ -f "$output_dir/$CONTRACTNAME.dot" ] && mv "$output_dir/$CONTRACTNAME.dot" "$output_dir/$CONTRACTNAME-old.dot"
7+
yarn sol2uml storage ./ -c "$CONTRACTNAME" -o "$output_dir/$CONTRACTNAME.dot" -f dot
8+
diff "$output_dir/$CONTRACTNAME-old.dot" "$output_dir/$CONTRACTNAME.dot"
9+
if [[ $? != "0" ]]
10+
then
11+
CHANGED=1
12+
fi
13+
done
14+
if [[ $CHANGED == 1 ]]
15+
then
16+
exit 1
17+
fi

test/storage/L1CustomGateway.dot

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
2 [label="L1CustomGateway \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { unallocated (12) | address: L1ArbitrumGateway.inbox (20) } | { <7> mapping\(bytes32=\>ExitData\): L1ArbitrumExtendedGateway.redirectedExits (32) } | { mapping\(address=\>address\): l1ToL2Token (32) } | { unallocated (12) | address: owner (20) } | { unallocated (12) | address: whitelist (20) } | { uint256: _status (32) }}}"]
9+
10+
1 [label="ExitData \<\<Struct\>\>\n | {{ offset | 0 | 1} | { type: variable (bytes) | { unallocated (11) | address: _newTo (20) | bool: isExit (1) } | { bytes: _newData (32) }}}"]
11+
12+
2:7 -> 1
13+
}

test/storage/L1ERC20Gateway.dot

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
2 [label="L1ERC20Gateway \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { unallocated (12) | address: L1ArbitrumGateway.inbox (20) } | { <7> mapping\(bytes32=\>ExitData\): L1ArbitrumExtendedGateway.redirectedExits (32) } | { bytes32: cloneableProxyHash (32) } | { unallocated (12) | address: l2BeaconProxyFactory (20) } | { unallocated (12) | address: whitelist (20) } | { uint256: _status (32) }}}"]
9+
10+
1 [label="ExitData \<\<Struct\>\>\n | {{ offset | 0 | 1} | { type: variable (bytes) | { unallocated (11) | address: _newTo (20) | bool: isExit (1) } | { bytes: _newData (32) }}}"]
11+
12+
2:7 -> 1
13+
}

test/storage/L1GatewayRouter.dot

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
1 [label="L1GatewayRouter \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3 | 4 | 5 | 6} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: WhitelistConsumer.whitelist (20) } | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { mapping\(address=\>address\): GatewayRouter.l1TokenToGateway (32) } | { unallocated (12) | address: GatewayRouter.defaultGateway (20) } | { unallocated (12) | address: owner (20) } | { unallocated (12) | address: inbox (20) }}}"]
9+
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
2 [label="L1ReverseCustomGateway \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { unallocated (12) | address: L1ArbitrumGateway.inbox (20) } | { <7> mapping\(bytes32=\>ExitData\): L1ArbitrumExtendedGateway.redirectedExits (32) } | { mapping\(address=\>address\): L1CustomGateway.l1ToL2Token (32) } | { unallocated (12) | address: L1CustomGateway.owner (20) } | { unallocated (12) | address: L1CustomGateway.whitelist (20) } | { uint256: L1CustomGateway._status (32) }}}"]
9+
10+
1 [label="ExitData \<\<Struct\>\>\n | {{ offset | 0 | 1} | { type: variable (bytes) | { unallocated (11) | address: _newTo (20) | bool: isExit (1) } | { bytes: _newData (32) }}}"]
11+
12+
2:7 -> 1
13+
}

test/storage/L1WethGateway.dot

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
2 [label="L1WethGateway \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3 | 4 | 5} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { unallocated (12) | address: L1ArbitrumGateway.inbox (20) } | { <7> mapping\(bytes32=\>ExitData\): L1ArbitrumExtendedGateway.redirectedExits (32) } | { unallocated (12) | address: l1Weth (20) } | { unallocated (12) | address: l2Weth (20) }}}"]
9+
10+
1 [label="ExitData \<\<Struct\>\>\n | {{ offset | 0 | 1} | { type: variable (bytes) | { unallocated (11) | address: _newTo (20) | bool: isExit (1) } | { bytes: _newData (32) }}}"]
11+
12+
2:7 -> 1
13+
}

test/storage/L2CustomGateway.dot

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
digraph StorageDiagram {
3+
rankdir=LR
4+
arrowhead=open
5+
bgcolor="white"
6+
edge [color="black"]
7+
node [shape=record, style=filled, color="black", fillcolor="gray95", fontcolor="black", fontname="Courier New"]
8+
1 [label="L2CustomGateway \<\<Contract\>\>\n | {{ slot | 0 | 1 | 2 | 3} | { type: \<inherited contract\>.variable (bytes) | { unallocated (12) | address: TokenGateway.counterpartGateway (20) } | { unallocated (12) | address: TokenGateway.router (20) } | { uint256: L2ArbitrumGateway.exitNum (32) } | { mapping\(address=\>address\): l1ToL2Token (32) }}}"]
9+
10+
}

0 commit comments

Comments
 (0)