diff --git a/slither.db.json b/slither.db.json index 174cede227..b1bf6c9287 100644 --- a/slither.db.json +++ b/slither.db.json @@ -1,4 +1,386 @@ [ + { + "elements": [ + { + "type": "node", + "name": "_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken)", + "source_mapping": { + "start": 14536, + "length": 53, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [341], + "starting_column": 9, + "ending_column": 62 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "createTokenBridge", + "source_mapping": { + "start": 8206, + "length": 8378, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [ + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, 391 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "L1AtomicTokenBridgeCreator", + "source_mapping": { + "start": 2103, + "length": 21727, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [ + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, + 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, + 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, + 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 570, 571, 572 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "createTokenBridge(address,address,uint256,uint256)" + } + } + } + }, + { + "type": "node", + "name": "_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken)", + "source_mapping": { + "start": 14536, + "length": 53, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [341], + "starting_column": 9, + "ending_column": 62 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "createTokenBridge", + "source_mapping": { + "start": 8206, + "length": 8378, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [ + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, 391 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "L1AtomicTokenBridgeCreator", + "source_mapping": { + "start": 2103, + "length": 21727, + "filename_relative": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol", + "is_dependency": false, + "lines": [ + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, + 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, + 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, + 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, + 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, + 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, + 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 570, 571, 572 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "createTokenBridge(address,address,uint256,uint256)" + } + } + } + } + ], + "description": "Multiple retryable tickets created in the same function:\n\t -_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#341)\n\t -_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken) (contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#341)\n", + "markdown": "Multiple retryable tickets created in the same function:\n\t -[_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L341)\n\t -[_deployL2Factory(inbox,gasPriceBid,isUsingFeeToken)](contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L341)\n", + "first_markdown_element": "contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol#L341", + "id": "a5e3feb7f2c59d43132c3ae5f4b1d458ebcc490d790a35328f9b5374e676bfac", + "check": "out-of-order-retryable", + "impact": "Medium", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "node", + "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", + "source_mapping": { + "start": 4464, + "length": 82, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [113], + "starting_column": 9, + "ending_column": 91 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "_sendRetryableUsingEth", + "source_mapping": { + "start": 3088, + "length": 1814, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [ + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "L1TokenBridgeRetryableSender", + "source_mapping": { + "start": 1390, + "length": 5848, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [ + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)" + } + } + } + }, + { + "type": "node", + "name": "_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)", + "source_mapping": { + "start": 4464, + "length": 82, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [113], + "starting_column": 9, + "ending_column": 91 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "_sendRetryableUsingEth", + "source_mapping": { + "start": 3088, + "length": 1814, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [ + 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "L1TokenBridgeRetryableSender", + "source_mapping": { + "start": 1390, + "length": 5848, + "filename_relative": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_absolute": "/Users/goran/repos/offchain/token-bridge-contracts/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "filename_short": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol", + "is_dependency": false, + "lines": [ + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, + 188, 189, 190, 191, 192, 193 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "_sendRetryableUsingEth(RetryableParams,L2TemplateAddresses,L1DeploymentAddresses,address,address,address,address)" + } + } + } + } + ], + "description": "Multiple retryable tickets created in the same function:\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n\t -_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data) (contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#113)\n", + "markdown": "Multiple retryable tickets created in the same function:\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n\t -[_createRetryableUsingEth(retryableParams,maxSubmissionCost,retryableValue,data)](contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113)\n", + "first_markdown_element": "contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol#L113", + "id": "17648cf433b86bf06bcab3f179d37fe19e73adff495e0e9485ce4b5d2d22a91b", + "check": "out-of-order-retryable", + "impact": "Medium", + "confidence": "Medium" + }, { "elements": [ { diff --git a/test-foundry/L2ArbitrumGateway.t.sol b/test-foundry/L2ArbitrumGateway.t.sol new file mode 100644 index 0000000000..c9e0a42908 --- /dev/null +++ b/test-foundry/L2ArbitrumGateway.t.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; + +import {L2ArbitrumGateway} from "contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol"; +import {ArbSysMock} from "contracts/tokenbridge/test/ArbSysMock.sol"; +import {ITokenGateway} from "contracts/tokenbridge/libraries/gateway/ITokenGateway.sol"; + +abstract contract L2ArbitrumGatewayTest is Test { + L2ArbitrumGateway public l2Gateway; + ArbSysMock public arbSysMock = new ArbSysMock(); + + address public router = makeAddr("router"); + address public l1Counterpart = makeAddr("l1Counterpart"); + + // token transfer params + address public receiver = makeAddr("to"); + address public sender = makeAddr("from"); + uint256 public amount = 2400; + + /* solhint-disable func-name-mixedcase */ + function test_getOutboundCalldata() public { + address token = makeAddr("token"); + bytes memory data = new bytes(340); + + bytes memory expected = abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + token, + sender, + receiver, + amount, + abi.encode(0, data) + ); + bytes memory actual = l2Gateway.getOutboundCalldata(token, sender, receiver, amount, data); + + assertEq(actual, expected, "Invalid outbound calldata"); + } + + function test_finalizeInboundTransfer() public virtual; + function test_finalizeInboundTransfer_WithCallHook() public virtual; + + function test_outboundTransfer() public virtual; + + function test_outboundTransfer_4Args() public virtual; + + function test_outboundTransfer_revert_ExtraDataDisabled() public { + vm.expectRevert("EXTRA_DATA_DISABLED"); + bytes memory extraData = new bytes(0x1234); + l2Gateway.outboundTransfer(address(100), address(101), 200, 0, 0, extraData); + } + + function test_outboundTransfer_revert_NoValue() public { + vm.expectRevert("NO_VALUE"); + l2Gateway.outboundTransfer{value: 1 ether}( + address(100), address(101), 200, 0, 0, new bytes(0) + ); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public virtual; + + function test_outboundTransfer_revert_TokenNotDeployed() public { + address token = makeAddr("someToken"); + vm.expectRevert("TOKEN_NOT_DEPLOYED"); + l2Gateway.outboundTransfer(token, address(101), 200, 0, 0, new bytes(0)); + } + + //// + // Event declarations + //// + event DepositFinalized( + address indexed l1Token, address indexed _from, address indexed _receiver, uint256 _amount + ); + + event WithdrawalInitiated( + address l1Token, + address indexed _from, + address indexed _receiver, + uint256 indexed _l2ToL1Id, + uint256 _exitNum, + uint256 _amount + ); + + event TxToL1( + address indexed _from, address indexed _receiver, uint256 indexed _id, bytes _data + ); +} diff --git a/test-foundry/L2CustomGateway.t.sol b/test-foundry/L2CustomGateway.t.sol new file mode 100644 index 0000000000..c464b21160 --- /dev/null +++ b/test-foundry/L2CustomGateway.t.sol @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L2ArbitrumGateway.t.sol"; +import {L2CustomGateway, ERC20} from "contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol"; +import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +contract L2CustomGatewayTest is L2ArbitrumGatewayTest { + L2CustomGateway public l2CustomGateway; + address public l1CustomToken = makeAddr("l1CustomToken"); + + function setUp() public virtual { + l2CustomGateway = new L2CustomGateway(); + l2Gateway = L2ArbitrumGateway(address(l2CustomGateway)); + + L2CustomGateway(l2CustomGateway).initialize(l1Counterpart, router); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress_NonRegistered() public { + address nonRegisteredL1Token = makeAddr("nonRegisteredL1Token"); + + assertEq( + l2CustomGateway.calculateL2TokenAddress(nonRegisteredL1Token), + address(0), + "Invalid L2 token" + ); + } + + function test_calculateL2TokenAddress_Registered() public virtual { + address l2CustomToken = _registerToken(); + assertEq( + l2CustomGateway.calculateL2TokenAddress(l1CustomToken), + l2CustomToken, + "Invalid L2 token" + ); + } + + function test_finalizeInboundTransfer() public virtual override { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + // register custom token + address l2CustomToken = _registerToken(); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1CustomToken, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver; + assertEq(ERC20(l2CustomToken).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_finalizeInboundTransfer_NoL2TokenFound() public { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + // check that withdrawal is triggered occurs when deposit is halted + bytes memory expectedData = l2CustomGateway.getOutboundCalldata( + l1CustomToken, address(l2CustomGateway), sender, amount, new bytes(0) + ); + vm.expectEmit(true, true, true, true); + emit TxToL1(address(l2CustomGateway), l1Counterpart, 0, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, address(l2CustomGateway), sender, 0, 0, amount); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + } + + function test_finalizeInboundTransfer_UnexpectedL1Address() public { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + /// L2 token returns unexpected L1 address + address l2CustomToken = _registerToken(); + address notOriginalL1Token = makeAddr("notOriginalL1Token"); + vm.mockCall( + address(l2CustomToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(notOriginalL1Token) + ); + + // check that withdrawal is triggered occurs when deposit is halted + bytes memory expectedData = l2CustomGateway.getOutboundCalldata( + l1CustomToken, address(l2CustomGateway), sender, amount, new bytes(0) + ); + vm.expectEmit(true, true, true, true); + emit TxToL1(address(l2CustomGateway), l1Counterpart, 0, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, address(l2CustomGateway), sender, 0, 0, amount); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + } + + function test_finalizeInboundTransfer_NoL1AddressImplemented() public { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + /// L2 token returns doesn't implement l1Address() + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = l1CustomToken; + + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(new Empty()); + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.registerTokenFromL1(l1Tokens, l2Tokens); + + // check that withdrawal is triggered occurs + bytes memory expectedData = l2CustomGateway.getOutboundCalldata( + l1CustomToken, address(l2CustomGateway), sender, amount, new bytes(0) + ); + vm.expectEmit(true, true, true, true); + emit TxToL1(address(l2CustomGateway), l1Counterpart, 0, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, address(l2CustomGateway), sender, 0, 0, amount); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + } + + function test_finalizeInboundTransfer_WithCallHook() public virtual override { + /// deposit params + bytes memory gatewayData = abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ); + bytes memory callHookData = new bytes(0x1); + + // register custom token + address l2CustomToken = _registerToken(); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1CustomToken, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver; + assertEq(ERC20(l2CustomToken).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_initialize() public { + L2CustomGateway gateway = new L2CustomGateway(); + L2CustomGateway(gateway).initialize(l1Counterpart, router); + + assertEq(gateway.counterpartGateway(), l1Counterpart, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + } + + function test_initialize_revert_BadRouter() public { + L2CustomGateway gateway = new L2CustomGateway(); + vm.expectRevert("BAD_ROUTER"); + L2CustomGateway(gateway).initialize(l1Counterpart, address(0)); + } + + function test_initialize_revert_InvalidCounterpart() public { + L2CustomGateway gateway = new L2CustomGateway(); + vm.expectRevert("INVALID_COUNTERPART"); + L2CustomGateway(gateway).initialize(address(0), router); + } + + function test_initialize_revert_AlreadyInit() public { + L2CustomGateway gateway = new L2CustomGateway(); + L2CustomGateway(gateway).initialize(l1Counterpart, router); + vm.expectRevert("ALREADY_INIT"); + L2CustomGateway(gateway).initialize(l1Counterpart, router); + } + + function test_outboundTransfer() public virtual override { + // create and init custom l2Token + address l2CustomToken = _registerToken(); + + // mint token to user + deal(l2CustomToken, sender, 100 ether); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2CustomGateway.getOutboundCalldata(l1CustomToken, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2CustomGateway.outboundTransfer(l1CustomToken, receiver, amount, 0, 0, data); + } + + function test_outboundTransfer_4Args() public virtual override { + // create and init custom l2Token + address l2CustomToken = _registerToken(); + + // mint token to user + deal(l2CustomToken, sender, 100 ether); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2CustomGateway.getOutboundCalldata(l1CustomToken, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2CustomGateway.outboundTransfer(l1CustomToken, receiver, amount, data); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public virtual override { + // create and init custom l2Token + address l2CustomToken = _registerToken(); + + // mock invalid L1 token ref + address notOriginalL1Token = makeAddr("notOriginalL1Token"); + vm.mockCall( + address(l2CustomToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(notOriginalL1Token) + ); + + vm.expectRevert("NOT_EXPECTED_L1_TOKEN"); + l2Gateway.outboundTransfer(l1CustomToken, address(101), 200, 0, 0, new bytes(0)); + } + + function test_postUpgradeInit_revert_NotFromAdmin() public { + ProxyAdmin pa = new ProxyAdmin(); + L2CustomGateway _l2Gateway = new L2CustomGateway(); + L2CustomGateway proxy = L2CustomGateway( + address(new TransparentUpgradeableProxy(address(_l2Gateway), address(pa), "")) + ); + + // no other logic implemented currently + vm.expectRevert("NOT_FROM_ADMIN"); + proxy.postUpgradeInit(); + } + + function test_registerTokenFromL1() public { + address[] memory l1Tokens = new address[](2); + l1Tokens[0] = makeAddr("l1Token0"); + l1Tokens[1] = makeAddr("l1Token1"); + + address[] memory l2Tokens = new address[](2); + l2Tokens[0] = makeAddr("l2Token0"); + l2Tokens[1] = makeAddr("l2Token1"); + + // expect events + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[0], l2Tokens[0]); + emit TokenSet(l1Tokens[1], l2Tokens[1]); + + // register + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.registerTokenFromL1(l1Tokens, l2Tokens); + + // checks + assertEq(l2CustomGateway.l1ToL2Token(l1Tokens[0]), l2Tokens[0], "Invalid registeration 0"); + assertEq(l2CustomGateway.l1ToL2Token(l1Tokens[1]), l2Tokens[1], "Invalid registeration 1"); + } + + function test_registerTokenFromL1_revert_OnlyCounterpartGateway() public { + vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); + l2CustomGateway.registerTokenFromL1(new address[](0), new address[](0)); + } + + //// + // Internal helper functions + //// + function _registerToken() internal virtual returns (address) { + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = l1CustomToken; + + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(new L2CustomToken(address(l2CustomGateway), address(l1CustomToken))); + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.registerTokenFromL1(l1Tokens, l2Tokens); + + return l2Tokens[0]; + } + + //// + // Event declarations + //// + event TokenSet(address indexed l1Address, address indexed l2Address); +} + +contract L2CustomToken is L2GatewayToken { + constructor(address _l2CustomGateway, address _l1CustomToken) { + L2GatewayToken._initialize("L2 token", "L2", 18, _l2CustomGateway, _l1CustomToken); + } +} + +contract Empty {} diff --git a/test-foundry/L2ERC20Gateway.t.sol b/test-foundry/L2ERC20Gateway.t.sol new file mode 100644 index 0000000000..0ea37a5650 --- /dev/null +++ b/test-foundry/L2ERC20Gateway.t.sol @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L2ArbitrumGateway.t.sol"; +import {L2ERC20Gateway} from "contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol"; +import {StandardArbERC20} from "contracts/tokenbridge/arbitrum/StandardArbERC20.sol"; +import { + BeaconProxyFactory, + ClonableBeaconProxy +} from "contracts/tokenbridge/libraries/ClonableBeaconProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; + +contract L2ERC20GatewayTest is L2ArbitrumGatewayTest { + L2ERC20Gateway public l2StandardGateway; + address public l2BeaconProxyFactory; + + address public l1Token = makeAddr("l1Token"); + + function setUp() public virtual { + l2StandardGateway = new L2ERC20Gateway(); + l2Gateway = L2ArbitrumGateway(address(l2StandardGateway)); + + // create beacon + StandardArbERC20 standardArbERC20 = new StandardArbERC20(); + UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); + l2BeaconProxyFactory = address(new BeaconProxyFactory()); + BeaconProxyFactory(l2BeaconProxyFactory).initialize(address(beacon)); + + L2ERC20Gateway(l2StandardGateway).initialize(l1Counterpart, router, l2BeaconProxyFactory); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress() public { + assertEq( + l2StandardGateway.getUserSalt(l1Token), + keccak256(abi.encode(l1Token)), + "Invalid user salt" + ); + } + + function test_cloneableProxyHash() public { + assertEq( + l2StandardGateway.cloneableProxyHash(), + keccak256(type(ClonableBeaconProxy).creationCode), + "Invalid proxy hash" + ); + } + + function test_finalizeInboundTransfer() public override { + /// deposit params + bytes memory gatewayData = abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ); + bytes memory callHookData = new bytes(0); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1Token, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2StandardGateway.finalizeInboundTransfer( + l1Token, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver + address expectedL2Address = l2StandardGateway.calculateL2TokenAddress(l1Token); + assertEq( + StandardArbERC20(expectedL2Address).balanceOf(receiver), + amount, + "Invalid receiver balance" + ); + } + + function test_finalizeInboundTransfer_WithCallHook() public override { + /// deposit params + bytes memory gatewayData = abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ); + bytes memory callHookData = new bytes(0x1); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1Token, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2StandardGateway.finalizeInboundTransfer( + l1Token, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver + address expectedL2Address = l2StandardGateway.calculateL2TokenAddress(l1Token); + assertEq( + StandardArbERC20(expectedL2Address).balanceOf(receiver), + amount, + "Invalid receiver balance" + ); + } + + function test_finalizeInboundTransfer_ShouldHalt() public { + /// deposit params + bytes memory gatewayData = abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ); + bytes memory callHookData = new bytes(0); + + // mock incorrect address calculation + address notL2Token = makeAddr("notL2Token"); + vm.mockCall( + address(l2BeaconProxyFactory), + abi.encodeWithSignature( + "calculateExpectedAddress(address,bytes32)", + address(l2StandardGateway), + l2StandardGateway.getUserSalt(l1Token) + ), + abi.encode(notL2Token) + ); + + // check that withdrawal is triggered occurs when deposit is halted + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1Token, address(l2StandardGateway), sender, 0, 0, amount); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2StandardGateway.finalizeInboundTransfer( + l1Token, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check L2 token hasn't been creted + assertEq(address(notL2Token).code.length, 0, "L2 token isn't supposed to be created"); + } + + function test_getUserSalt() public { + assertEq( + l2StandardGateway.getUserSalt(l1Token), + keccak256(abi.encode(l1Token)), + "Invalid user salt" + ); + } + + function test_initialize() public { + L2ERC20Gateway gateway = new L2ERC20Gateway(); + L2ERC20Gateway(gateway).initialize(l1Counterpart, router, l2BeaconProxyFactory); + + assertEq(gateway.counterpartGateway(), l1Counterpart, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.beaconProxyFactory(), l2BeaconProxyFactory, "Invalid beacon"); + } + + function test_initialize_revert_InvalidBeacon() public { + L2ERC20Gateway gateway = new L2ERC20Gateway(); + vm.expectRevert("INVALID_BEACON"); + L2ERC20Gateway(gateway).initialize(l1Counterpart, router, address(0)); + } + + function test_initialize_revert_BadRouter() public { + L2ERC20Gateway gateway = new L2ERC20Gateway(); + vm.expectRevert("BAD_ROUTER"); + L2ERC20Gateway(gateway).initialize(l1Counterpart, address(0), l2BeaconProxyFactory); + } + + function test_initialize_revert_InvalidCounterpart() public { + L2ERC20Gateway gateway = new L2ERC20Gateway(); + vm.expectRevert("INVALID_COUNTERPART"); + L2ERC20Gateway(gateway).initialize(address(0), router, l2BeaconProxyFactory); + } + + function test_initialize_revert_AlreadyInit() public { + L2ERC20Gateway gateway = new L2ERC20Gateway(); + L2ERC20Gateway(gateway).initialize(l1Counterpart, router, l2BeaconProxyFactory); + vm.expectRevert("ALREADY_INIT"); + L2ERC20Gateway(gateway).initialize(l1Counterpart, router, l2BeaconProxyFactory); + } + + function test_outboundTransfer() public override { + // create and init standard l2Token + bytes32 salt = keccak256(abi.encode(l1Token)); + vm.startPrank(address(l2Gateway)); + address l2Token = BeaconProxyFactory(l2BeaconProxyFactory).createProxy(salt); + StandardArbERC20(l2Token).bridgeInit( + l1Token, + abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ) + ); + vm.stopPrank(); + + // mint token to user + deal(l2Token, sender, 100 ether); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2Gateway.getOutboundCalldata(l1Token, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1Token, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2Gateway.outboundTransfer(l1Token, receiver, amount, 0, 0, data); + } + + function test_outboundTransfer_4Args() public override { + // create and init standard l2Token + bytes32 salt = keccak256(abi.encode(l1Token)); + vm.startPrank(address(l2Gateway)); + address l2Token = BeaconProxyFactory(l2BeaconProxyFactory).createProxy(salt); + StandardArbERC20(l2Token).bridgeInit( + l1Token, + abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ) + ); + vm.stopPrank(); + + // mint token to user + deal(l2Token, sender, 100 ether); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2Gateway.getOutboundCalldata(l1Token, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1Token, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2Gateway.outboundTransfer(l1Token, receiver, amount, data); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public override { + /// register l1Token + bytes32 salt = keccak256(abi.encode(l1Token)); + vm.startPrank(address(l2Gateway)); + address l2Token = BeaconProxyFactory(l2BeaconProxyFactory).createProxy(salt); + StandardArbERC20(l2Token).bridgeInit( + l1Token, + abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ) + ); + vm.stopPrank(); + + // mock invalid L1 token ref + address notOriginalL1Token = makeAddr("notOriginalL1Token"); + vm.mockCall( + address(l2Token), abi.encodeWithSignature("l1Address()"), abi.encode(notOriginalL1Token) + ); + + vm.expectRevert("NOT_EXPECTED_L1_TOKEN"); + l2Gateway.outboundTransfer(l1Token, address(101), 200, 0, 0, new bytes(0)); + } +} diff --git a/test-foundry/L2GatewayRouter.t.sol b/test-foundry/L2GatewayRouter.t.sol new file mode 100644 index 0000000000..2a0bac95f1 --- /dev/null +++ b/test-foundry/L2GatewayRouter.t.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import {GatewayRouterTest} from "./GatewayRouter.t.sol"; +import {L2GatewayRouter} from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; +import {L2ERC20Gateway} from "contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol"; +import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; +import {StandardArbERC20} from "contracts/tokenbridge/arbitrum/StandardArbERC20.sol"; +import {BeaconProxyFactory} from "contracts/tokenbridge/libraries/ClonableBeaconProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import {ArbSysMock} from "contracts/tokenbridge/test/ArbSysMock.sol"; + +contract L2GatewayRouterTest is GatewayRouterTest { + L2GatewayRouter public l2Router; + ArbSysMock public arbSysMock = new ArbSysMock(); + + address public user = makeAddr("user"); + address public counterpartGateway = makeAddr("counterpartGateway"); + address public beaconProxyFactory; + + function setUp() public virtual { + defaultGateway = address(new L2ERC20Gateway()); + + // create beacon + StandardArbERC20 standardArbERC20 = new StandardArbERC20(); + UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); + beaconProxyFactory = address(new BeaconProxyFactory()); + BeaconProxyFactory(beaconProxyFactory).initialize(address(beacon)); + + router = new L2GatewayRouter(); + l2Router = L2GatewayRouter(address(router)); + l2Router.initialize(counterpartGateway, defaultGateway); + + L2ERC20Gateway(defaultGateway).initialize( + counterpartGateway, address(l2Router), beaconProxyFactory + ); + } + + /* solhint-disable func-name-mixedcase */ + function test_initialize() public { + L2GatewayRouter router = new L2GatewayRouter(); + + router.initialize(counterpartGateway, defaultGateway); + + assertEq(router.router(), address(0), "Invalid router"); + assertEq(router.counterpartGateway(), counterpartGateway, "Invalid counterpartGateway"); + assertEq(router.defaultGateway(), defaultGateway, "Invalid defaultGateway"); + } + + function test_outboundTransfer() public { + address l1Token = makeAddr("l1Token"); + + // create and init standard l2Token + bytes32 salt = keccak256(abi.encode(l1Token)); + vm.startPrank(defaultGateway); + address l2Token = BeaconProxyFactory(beaconProxyFactory).createProxy(salt); + StandardArbERC20(l2Token).bridgeInit( + l1Token, + abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ) + ); + vm.stopPrank(); + + // mint token to user + deal(l2Token, user, 100 ether); + + // withdrawal params + address to = makeAddr("to"); + uint256 amount = 2400; + bytes memory data = new bytes(0); + + // event + vm.expectEmit(true, true, true, true); + emit TransferRouted(l1Token, user, to, defaultGateway); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(user); + l2Router.outboundTransfer(l1Token, to, amount, data); + } + + function test_setDefaultGateway() public { + address newDefaultGateway = makeAddr("newDefaultGateway"); + + vm.expectEmit(true, true, true, true); + emit DefaultGatewayUpdated(newDefaultGateway); + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(counterpartGateway)); + l2Router.setDefaultGateway(newDefaultGateway); + + assertEq(l2Router.defaultGateway(), newDefaultGateway, "New default gateway not set"); + } + + function test_setDefaultGateway_revert_OnlyCounterpart() public { + vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); + l2Router.setDefaultGateway(address(2)); + } + + function test_setGateway() public { + address[] memory tokens = new address[](1); + tokens[0] = makeAddr("l1Token"); + address[] memory gateways = new address[](1); + gateways[0] = makeAddr("gateway"); + + vm.expectEmit(true, true, true, true); + emit GatewaySet(tokens[0], gateways[0]); + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(counterpartGateway)); + l2Router.setGateway(tokens, gateways); + + assertEq(l2Router.l1TokenToGateway(tokens[0]), gateways[0], "Gateway[0] not set"); + } + + function test_setGateway_revert_OnlyCounterpart() public { + vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); + l2Router.setGateway(new address[](1), new address[](1)); + } + + function test_setGateway_revert_WrongLengths() public { + vm.expectRevert(); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(counterpartGateway)); + l2Router.setGateway(new address[](1), new address[](2)); + } + + //// + // Event declarations + //// + + event TransferRouted( + address indexed token, address indexed _userFrom, address indexed _userTo, address gateway + ); + + event GatewaySet(address indexed l1Token, address indexed gateway); + event DefaultGatewayUpdated(address newDefaultGateway); +} diff --git a/test-foundry/L2ReverseCustomGateway.t.sol b/test-foundry/L2ReverseCustomGateway.t.sol new file mode 100644 index 0000000000..ba08345c09 --- /dev/null +++ b/test-foundry/L2ReverseCustomGateway.t.sol @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L2CustomGateway.t.sol"; +import {L2ReverseCustomGateway} from + "contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol"; +import {ReverseTestCustomTokenL1} from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; +import {ReverseTestArbCustomToken} from "contracts/tokenbridge/test/TestArbCustomToken.sol"; + +contract L2ReverseCustomGatewayTest is L2CustomGatewayTest { + L2ReverseCustomGateway public l2ReverseCustomGateway; + + ReverseTestArbCustomToken public l2MintedToken; + + function setUp() public override { + l2ReverseCustomGateway = new L2ReverseCustomGateway(); + l2Gateway = L2ArbitrumGateway(address(l2ReverseCustomGateway)); + l2CustomGateway = L2CustomGateway(address(l2ReverseCustomGateway)); + + L2ReverseCustomGateway(l2ReverseCustomGateway).initialize(l1Counterpart, router); + + l2MintedToken = + new ReverseTestArbCustomToken(address(l2ReverseCustomGateway), makeAddr("l1Token")); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress_Registered() public override { + address l1CustomToken = _registerToken(); + assertEq( + l2CustomGateway.calculateL2TokenAddress(l1CustomToken), + address(l2MintedToken), + "Invalid L2 token" + ); + } + + function test_finalizeInboundTransfer() public override { + // fund gateway with tokens being withdrawn + vm.prank(address(l2ReverseCustomGateway)); + l2MintedToken.mint(); + + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + // register custom token + address l1CustomToken = _registerToken(); + + vm.mockCall( + address(l2MintedToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(l1CustomToken) + ); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1CustomToken, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been released to receiver; + assertEq( + ERC20(address(l2MintedToken)).balanceOf(receiver), amount, "Invalid receiver balance" + ); + } + + function test_finalizeInboundTransfer_WithCallHook() public override { + // fund gateway with tokens being withdrawn + vm.prank(address(l2ReverseCustomGateway)); + l2MintedToken.mint(); + + /// deposit params + bytes memory gatewayData = abi.encode( + abi.encode(bytes("Name")), abi.encode(bytes("Symbol")), abi.encode(uint256(18)) + ); + bytes memory callHookData = new bytes(0x1); + + // register custom token + address l1CustomToken = _registerToken(); + + vm.mockCall( + address(l2MintedToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(l1CustomToken) + ); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1CustomToken, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2CustomGateway.finalizeInboundTransfer( + l1CustomToken, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been released to receiver; + assertEq( + ERC20(address(l2MintedToken)).balanceOf(receiver), amount, "Invalid receiver balance" + ); + } + + function test_outboundTransfer() public override { + // fund sender + vm.startPrank(sender); + l2MintedToken.mint(); + l2MintedToken.approve(address(l2CustomGateway), amount); + vm.stopPrank(); + + // create and init custom l2Token + address l1CustomToken = _registerToken(); + + vm.mockCall( + address(l2MintedToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(l1CustomToken) + ); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2CustomGateway.getOutboundCalldata(l1CustomToken, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2CustomGateway.outboundTransfer(l1CustomToken, receiver, amount, 0, 0, data); + } + + function test_outboundTransfer_4Args() public override { + // fund sender + vm.startPrank(sender); + l2MintedToken.mint(); + l2MintedToken.approve(address(l2CustomGateway), amount); + vm.stopPrank(); + + // create and init custom l2Token + address l1CustomToken = _registerToken(); + + vm.mockCall( + address(l2MintedToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(l1CustomToken) + ); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2CustomGateway.getOutboundCalldata(l1CustomToken, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1CustomToken, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2CustomGateway.outboundTransfer(l1CustomToken, receiver, amount, data); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public override { + // create and init custom l2Token + address l1CustomToken = _registerToken(); + + // mock invalid L1 token ref + address notOriginalL1Token = makeAddr("notOriginalL1Token"); + vm.mockCall( + address(l2MintedToken), + abi.encodeWithSignature("l1Address()"), + abi.encode(notOriginalL1Token) + ); + + vm.expectRevert("NOT_EXPECTED_L1_TOKEN"); + l2Gateway.outboundTransfer(l1CustomToken, address(101), 200, 0, 0, new bytes(0)); + } + + //// + // Internal helper functions + //// + function _registerToken() internal override returns (address) { + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = address( + new ReverseTestCustomTokenL1(address(l1Counterpart), makeAddr("counterpartGateway")) + ); + + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(l2MintedToken); + + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2ReverseCustomGateway.registerTokenFromL1(l1Tokens, l2Tokens); + + return l1Tokens[0]; + } +} diff --git a/test-foundry/L2WethGateway.t.sol b/test-foundry/L2WethGateway.t.sol new file mode 100644 index 0000000000..4f81f48ffe --- /dev/null +++ b/test-foundry/L2WethGateway.t.sol @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "./L2ArbitrumGateway.t.sol"; + +import {L2WethGateway} from "contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol"; +import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {aeWETH} from "contracts/tokenbridge/libraries/aeWETH.sol"; +import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +contract L2WethGatewayTest is L2ArbitrumGatewayTest { + L2WethGateway public l2WethGateway; + address public l2BeaconProxyFactory; + + address public l1Weth = makeAddr("l1Weth"); + address public l2Weth; + + function setUp() public virtual { + l2WethGateway = new L2WethGateway(); + l2Gateway = L2ArbitrumGateway(address(l2WethGateway)); + + ProxyAdmin pa = new ProxyAdmin(); + l2Weth = address(new TransparentUpgradeableProxy(address(new aeWETH()), address(pa), "")); + + L2WethGateway(l2WethGateway).initialize(l1Counterpart, router, l1Weth, l2Weth); + aeWETH(payable(l2Weth)).initialize("WETH", "WETH", 18, address(l2WethGateway), l1Weth); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress() public { + assertEq(l2WethGateway.calculateL2TokenAddress(l1Weth), l2Weth, "Invalid weth address"); + } + + function test_calculateL2TokenAddress_NotWeth() public { + address randomToken = makeAddr("randomToken"); + assertEq( + l2WethGateway.calculateL2TokenAddress(randomToken), address(0), "Invalid weth address" + ); + } + + function test_finalizeInboundTransfer() public override { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + // fund gateway + vm.deal(address(l2WethGateway), 100 ether); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1Weth, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2WethGateway.finalizeInboundTransfer( + l1Weth, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver; + assertEq(aeWETH(payable(l2Weth)).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_finalizeInboundTransfer_WithCallHook() public override { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0x1); + + // fund gateway + vm.deal(address(l2WethGateway), 100 ether); + + /// events + vm.expectEmit(true, true, true, true); + emit DepositFinalized(l1Weth, sender, receiver, amount); + + /// finalize deposit + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2WethGateway.finalizeInboundTransfer( + l1Weth, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + + /// check tokens have been minted to receiver; + assertEq(aeWETH(payable(l2Weth)).balanceOf(receiver), amount, "Invalid receiver balance"); + } + + function test_finalizeInboundTransfer_ShouldHalt() public { + /// deposit params + bytes memory gatewayData = new bytes(0); + bytes memory callHookData = new bytes(0); + + address notL1Weth = makeAddr("notL1Weth"); + + // check that withdrawal is triggered occurs when deposit is halted + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(notL1Weth, address(l2WethGateway), sender, 0, 0, amount); + + vm.deal(address(l2WethGateway), 100 ether); + + /// finalize deposit + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(AddressAliasHelper.applyL1ToL2Alias(l1Counterpart)); + l2WethGateway.finalizeInboundTransfer( + notL1Weth, sender, receiver, amount, abi.encode(gatewayData, callHookData) + ); + } + + function test_initialize() public { + L2WethGateway gateway = new L2WethGateway(); + L2WethGateway(gateway).initialize(l1Counterpart, router, l1Weth, l2Weth); + + assertEq(gateway.counterpartGateway(), l1Counterpart, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.l1Weth(), l1Weth, "Invalid l1Weth"); + assertEq(gateway.l2Weth(), l2Weth, "Invalid l2Weth"); + } + + function test_initialize_revert_InvalidL1Weth() public { + L2WethGateway gateway = new L2WethGateway(); + vm.expectRevert("INVALID_L1WETH"); + address invalidL1Weth = address(0); + L2WethGateway(gateway).initialize(l1Counterpart, router, invalidL1Weth, l2Weth); + } + + function test_initialize_revert_InvalidL2Weth() public { + L2WethGateway gateway = new L2WethGateway(); + vm.expectRevert("INVALID_L2WETH"); + address invalidL2Weth = address(0); + L2WethGateway(gateway).initialize(l1Counterpart, router, l1Weth, invalidL2Weth); + } + + function test_outboundTransfer() public override { + // mint token to user + deal(address(this), 100 ether); + aeWETH(payable(l2Weth)).depositTo{value: 20 ether}(sender); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2WethGateway.getOutboundCalldata(l1Weth, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1Weth, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2WethGateway.outboundTransfer(l1Weth, receiver, amount, 0, 0, data); + } + + function test_outboundTransfer_4Args() public override { + // mint token to user + deal(address(this), 100 ether); + aeWETH(payable(l2Weth)).depositTo{value: 20 ether}(sender); + + // withdrawal params + bytes memory data = new bytes(0); + + // events + uint256 expectedId = 0; + bytes memory expectedData = + l2WethGateway.getOutboundCalldata(l1Weth, sender, receiver, amount, data); + vm.expectEmit(true, true, true, true); + emit TxToL1(sender, l1Counterpart, expectedId, expectedData); + + vm.expectEmit(true, true, true, true); + emit WithdrawalInitiated(l1Weth, sender, receiver, expectedId, 0, amount); + + // withdraw + vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); + vm.prank(sender); + l2WethGateway.outboundTransfer(l1Weth, receiver, amount, data); + } + + function test_outboundTransfer_revert_NotExpectedL1Token() public override { + // mock invalid L1 token ref + address notL1Weth = makeAddr("notL1Weth"); + vm.mockCall(address(l2Weth), abi.encodeWithSignature("l1Address()"), abi.encode(notL1Weth)); + + vm.expectRevert("NOT_EXPECTED_L1_TOKEN"); + l2WethGateway.outboundTransfer(l1Weth, address(101), 200, 0, 0, new bytes(0)); + } + + function test_receive() public { + vm.deal(address(this), 5 ether); + bool sent = payable(l2WethGateway).send(5 ether); + + assertTrue(sent, "Failed to send"); + assertEq(address(l2WethGateway).balance, 5 ether, "Invalid balance"); + } +} diff --git a/test-mutation/all-configs/config.tokenbridge-arbitrum.json b/test-mutation/all-configs/config.tokenbridge-arbitrum.json new file mode 100644 index 0000000000..85bc60d012 --- /dev/null +++ b/test-mutation/all-configs/config.tokenbridge-arbitrum.json @@ -0,0 +1,82 @@ +[ + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/ReverseArbToken.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + }, + { + "filename": "../contracts/tokenbridge/arbitrum/StandardArbERC20.sol", + "sourceroot": "..", + "solc_remappings": [ + "@openzeppelin=../node_modules/@openzeppelin", + "@arbitrum=../node_modules/@arbitrum" + ] + } +] diff --git a/test-mutation/config.json b/test-mutation/config.json index 13da9e7018..85bc60d012 100644 --- a/test-mutation/config.json +++ b/test-mutation/config.json @@ -1,6 +1,6 @@ [ { - "filename": "../contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -8,7 +8,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -16,7 +16,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -24,7 +24,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -32,7 +32,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -40,7 +40,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -48,7 +48,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol", + "filename": "../contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -56,7 +56,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -64,7 +64,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/ReverseArbToken.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", @@ -72,31 +72,7 @@ ] }, { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol", - "sourceroot": "..", - "solc_remappings": [ - "@openzeppelin=../node_modules/@openzeppelin", - "@arbitrum=../node_modules/@arbitrum" - ] - }, - { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol", - "sourceroot": "..", - "solc_remappings": [ - "@openzeppelin=../node_modules/@openzeppelin", - "@arbitrum=../node_modules/@arbitrum" - ] - }, - { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol", - "sourceroot": "..", - "solc_remappings": [ - "@openzeppelin=../node_modules/@openzeppelin", - "@arbitrum=../node_modules/@arbitrum" - ] - }, - { - "filename": "../contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol", + "filename": "../contracts/tokenbridge/arbitrum/StandardArbERC20.sol", "sourceroot": "..", "solc_remappings": [ "@openzeppelin=../node_modules/@openzeppelin", diff --git a/test-mutation/gambitTester.ts b/test-mutation/gambitTester.ts index 9450abb1ef..495f074826 100644 --- a/test-mutation/gambitTester.ts +++ b/test-mutation/gambitTester.ts @@ -13,7 +13,7 @@ const TEST_TIMES = [ 'remappings.txt', 'test-foundry', ] -const MAX_TASKS = Math.max(1, os.cpus().length - 1) +const MAX_TASKS = Math.max(1, os.cpus().length - 2) const execAsync = promisify(exec) const symlink = promisify(fs.symlink) @@ -123,7 +123,7 @@ async function _testMutant(mutant: Mutant): Promise { try { await execAsync(`forge build --root ${testDirectory}`) await execAsync( - `forge test --fail-fast --no-match-contract AtomicTokenBridgeCreatorTest --root ${testDirectory}` + `forge test --fail-fast --gas-limit 50000000 --no-match-contract AtomicTokenBridgeCreatorTest --root ${testDirectory}` ) mutantStatus = MutantStatus.SURVIVED } catch (error) {