diff --git a/.changeset/fuzzy-phones-tan.md b/.changeset/fuzzy-phones-tan.md new file mode 100644 index 0000000000000..96b06105e84e7 --- /dev/null +++ b/.changeset/fuzzy-phones-tan.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/contracts-bedrock': patch +--- + +Adds a fuzz input generator for testing Bedrock's `MerkleTrie.sol` diff --git a/go.work b/go.work index 9d05ab2d5bdfd..2c4e79f3e9f00 100644 --- a/go.work +++ b/go.work @@ -16,6 +16,7 @@ use ( ./op-node ./op-proposer ./op-service + ./packages/contracts-bedrock/go-fuzz ./proxyd ) diff --git a/op-bindings/bindings/erc20.go b/op-bindings/bindings/erc20.go index 766f6eb69b117..bf3e56650ed72 100644 --- a/op-bindings/bindings/erc20.go +++ b/op-bindings/bindings/erc20.go @@ -31,7 +31,7 @@ var ( // ERC20MetaData contains all meta data concerning the ERC20 contract. var ERC20MetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b5060405162000e3c38038062000e3c833981016040819052620000349162000127565b600362000042838262000220565b50600462000051828262000220565b505050620002ec565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200008257600080fd5b81516001600160401b03808211156200009f576200009f6200005a565b604051601f8301601f19908116603f01168101908282118183101715620000ca57620000ca6200005a565b81604052838152602092508683858801011115620000e757600080fd5b600091505b838210156200010b5785820183015181830184015290820190620000ec565b838211156200011d5760008385830101525b9695505050505050565b600080604083850312156200013b57600080fd5b82516001600160401b03808211156200015357600080fd5b620001618683870162000070565b935060208501519150808211156200017857600080fd5b50620001878582860162000070565b9150509250929050565b600181811c90821680620001a657607f821691505b602082108103620001c757634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021b57600081815260208120601f850160051c81016020861015620001f65750805b601f850160051c820191505b81811015620002175782815560010162000202565b5050505b505050565b81516001600160401b038111156200023c576200023c6200005a565b62000254816200024d845462000191565b84620001cd565b602080601f8311600181146200028c5760008415620002735750858301515b600019600386901b1c1916600185901b17855562000217565b600085815260208120601f198616915b82811015620002bd578886015182559484019460019091019084016200029c565b5085821015620002dc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610b4080620002fc6000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610194578063a9059cbb146101a7578063dd62ed3e146101ba57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461018c57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d6610200565b6040516100e3919061094a565b60405180910390f35b6100ff6100fa3660046109e6565b610292565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f366004610a10565b6102aa565b604051601281526020016100e3565b6100ff6101513660046109e6565b6102ce565b610113610164366004610a4c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100d661031a565b6100ff6101a23660046109e6565b610329565b6100ff6101b53660046109e6565b6103ff565b6101136101c8366004610a6e565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461020f90610aa1565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610aa1565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b6000336102a081858561040d565b5060019392505050565b6000336102b88582856105c0565b6102c3858585610697565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906102a09082908690610315908790610af4565b61040d565b60606004805461020f90610aa1565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156103f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102c3828686840361040d565b6000336102a0818585610697565b73ffffffffffffffffffffffffffffffffffffffff83166104af576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016103e9565b73ffffffffffffffffffffffffffffffffffffffff8216610552576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016103e9565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106915781811015610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103e9565b610691848484840361040d565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661073a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103e9565b73ffffffffffffffffffffffffffffffffffffffff82166107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016103e9565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016103e9565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082208585039055918516815290812080548492906108d7908490610af4565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161093d91815260200190565b60405180910390a3610691565b600060208083528351808285015260005b818110156109775785810183015185820160400152820161095b565b81811115610989576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e157600080fd5b919050565b600080604083850312156109f957600080fd5b610a02836109bd565b946020939093013593505050565b600080600060608486031215610a2557600080fd5b610a2e846109bd565b9250610a3c602085016109bd565b9150604084013590509250925092565b600060208284031215610a5e57600080fd5b610a67826109bd565b9392505050565b60008060408385031215610a8157600080fd5b610a8a836109bd565b9150610a98602084016109bd565b90509250929050565b600181811c90821680610ab557607f821691505b602082108103610aee577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008219821115610b2e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a", + Bin: "0x60806040523480156200001157600080fd5b5060405162000e2a38038062000e2a83398101604081905262000034916200011f565b600362000042838262000218565b50600462000051828262000218565b505050620002e4565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200008257600080fd5b81516001600160401b03808211156200009f576200009f6200005a565b604051601f8301601f19908116603f01168101908282118183101715620000ca57620000ca6200005a565b81604052838152602092508683858801011115620000e757600080fd5b600091505b838210156200010b5785820183015181830184015290820190620000ec565b600093810190920192909252949350505050565b600080604083850312156200013357600080fd5b82516001600160401b03808211156200014b57600080fd5b620001598683870162000070565b935060208501519150808211156200017057600080fd5b506200017f8582860162000070565b9150509250929050565b600181811c908216806200019e57607f821691505b602082108103620001bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200021357600081815260208120601f850160051c81016020861015620001ee5750805b601f850160051c820191505b818110156200020f57828155600101620001fa565b5050505b505050565b81516001600160401b038111156200023457620002346200005a565b6200024c8162000245845462000189565b84620001c5565b602080601f8311600181146200028457600084156200026b5750858301515b600019600386901b1c1916600185901b1785556200020f565b600085815260208120601f198616915b82811015620002b55788860151825594840194600190910190840162000294565b5085821015620002d45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610b3680620002f46000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80633950935111610081578063a457c2d71161005b578063a457c2d714610194578063a9059cbb146101a7578063dd62ed3e146101ba57600080fd5b8063395093511461014357806370a082311461015657806395d89b411461018c57600080fd5b806318160ddd116100b257806318160ddd1461010f57806323b872dd14610121578063313ce5671461013457600080fd5b806306fdde03146100ce578063095ea7b3146100ec575b600080fd5b6100d6610200565b6040516100e3919061094c565b60405180910390f35b6100ff6100fa3660046109e1565b610292565b60405190151581526020016100e3565b6002545b6040519081526020016100e3565b6100ff61012f366004610a0b565b6102ac565b604051601281526020016100e3565b6100ff6101513660046109e1565b6102d0565b610113610164366004610a47565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100d661031c565b6100ff6101a23660046109e1565b61032b565b6100ff6101b53660046109e1565b610401565b6101136101c8366004610a69565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60606003805461020f90610a9c565b80601f016020809104026020016040519081016040528092919081815260200182805461023b90610a9c565b80156102885780601f1061025d57610100808354040283529160200191610288565b820191906000526020600020905b81548152906001019060200180831161026b57829003601f168201915b5050505050905090565b6000336102a081858561040f565b60019150505b92915050565b6000336102ba8582856105c2565b6102c5858585610699565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906102a09082908690610317908790610aef565b61040f565b60606004805461020f90610a9c565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190838110156103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102c5828686840361040f565b6000336102a0818585610699565b73ffffffffffffffffffffffffffffffffffffffff83166104b1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff8216610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106935781811015610686576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103eb565b610693848484840361040f565b50505050565b73ffffffffffffffffffffffffffffffffffffffff831661073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff82166107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016103eb565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082208585039055918516815290812080548492906108d9908490610aef565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161093f91815260200190565b60405180910390a3610693565b600060208083528351808285015260005b818110156109795785810183015185820160400152820161095d565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109dc57600080fd5b919050565b600080604083850312156109f457600080fd5b6109fd836109b8565b946020939093013593505050565b600080600060608486031215610a2057600080fd5b610a29846109b8565b9250610a37602085016109b8565b9150604084013590509250925092565b600060208284031215610a5957600080fd5b610a62826109b8565b9392505050565b60008060408385031215610a7c57600080fd5b610a85836109b8565b9150610a93602084016109b8565b90509250929050565b600181811c90821680610ab057607f821691505b602082108103610ae9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b808201808211156102a6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000811000a", } // ERC20ABI is the input ABI used to generate the binding from. diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index 613ca36b378cd..249ac9676357a 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -10,7 +10,7 @@ GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74956) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35693) CrossDomainMessenger_Test:testFuzz_baseGas(uint32) (runs: 256, μ: 20196, ~: 20196) CrossDomainMessenger_Test:test_baseGas() (gas: 20054) -CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61809) +CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner() (gas: 61815) CrossDomainOwnable_Test:test_onlyOwner() (gas: 34861) CrossDomainOwnable_Test:test_revertOnlyOwner() (gas: 10530) CrossDomainOwnable2_Test:test_onlyOwner() (gas: 77782) @@ -131,27 +131,37 @@ LegacyERC20ETH_Test:test_mint() (gas: 10649) LegacyERC20ETH_Test:test_transfer() (gas: 10711) LegacyERC20ETH_Test:test_transferFrom() (gas: 12887) LegacyMessagePasser_Test:test_LegacyMessagePasser_passMessageToL1_Succeeds() (gas: 34519) -MerkleTrie_Test:test_get_reverts_corruptedProof() (gas: 5686) -MerkleTrie_Test:test_get_reverts_extraProofElements() (gas: 60560) -MerkleTrie_Test:test_get_reverts_invalidDataRemainder() (gas: 35827) -MerkleTrie_Test:test_get_reverts_invalidInternalNodeHash() (gas: 50763) -MerkleTrie_Test:test_get_reverts_nonexistentKey1() (gas: 59624) -MerkleTrie_Test:test_get_reverts_nonexistentKey2() (gas: 23359) -MerkleTrie_Test:test_get_reverts_smallerPathThanKey1() (gas: 53476) -MerkleTrie_Test:test_get_reverts_smallerPathThanKey2() (gas: 54913) -MerkleTrie_Test:test_get_reverts_wrongKeyProof() (gas: 53844) -MerkleTrie_Test:test_get_reverts_zeroBranchValueLength() (gas: 43222) -MerkleTrie_Test:test_get_reverts_zeroLengthKey() (gas: 15886) -MerkleTrie_Test:test_get_validProofSucceeds1() (gas: 61619) -MerkleTrie_Test:test_get_validProofSucceeds10() (gas: 50546) -MerkleTrie_Test:test_get_validProofSucceeds2() (gas: 71531) -MerkleTrie_Test:test_get_validProofSucceeds3() (gas: 32779) -MerkleTrie_Test:test_get_validProofSucceeds4() (gas: 23553) -MerkleTrie_Test:test_get_validProofSucceeds5() (gas: 84215) -MerkleTrie_Test:test_get_validProofSucceeds6() (gas: 72991) -MerkleTrie_Test:test_get_validProofSucceeds7() (gas: 79670) -MerkleTrie_Test:test_get_validProofSucceeds8() (gas: 50546) -MerkleTrie_Test:test_get_validProofSucceeds9() (gas: 50501) +MerkleTrie_Test:testFuzz_get_corruptedProof_reverts(bytes4) (runs: 256, μ: 78643, ~: 74433) +MerkleTrie_Test:testFuzz_get_emptyKey_reverts(bytes4) (runs: 256, μ: 33263, ~: 33495) +MerkleTrie_Test:testFuzz_get_extraProofElements_reverts(bytes4) (runs: 256, μ: 192689, ~: 193884) +MerkleTrie_Test:testFuzz_get_invalidDataRemainder_reverts(bytes4) (runs: 256, μ: 82410, ~: 79887) +MerkleTrie_Test:testFuzz_get_invalidInternalNodeHash_reverts(bytes4) (runs: 256, μ: 137634, ~: 142307) +MerkleTrie_Test:testFuzz_get_invalidLargeInternalHash_reverts(bytes4) (runs: 256, μ: 143153, ~: 145631) +MerkleTrie_Test:testFuzz_get_invalidRoot_reverts(bytes4) (runs: 256, μ: 137579, ~: 140414) +MerkleTrie_Test:testFuzz_get_partialProof_reverts(bytes4) (runs: 256, μ: 97449, ~: 103650) +MerkleTrie_Test:testFuzz_get_prefixedValidKey_reverts(bytes4) (runs: 256, μ: 146367, ~: 149444) +MerkleTrie_Test:testFuzz_get_validProofs_success(bytes4) (runs: 256, μ: 305718, ~: 305766) +MerkleTrie_Test:test_get_reverts_corruptedProof() (gas: 5756) +MerkleTrie_Test:test_get_reverts_extraProofElements() (gas: 60608) +MerkleTrie_Test:test_get_reverts_invalidDataRemainder() (gas: 35808) +MerkleTrie_Test:test_get_reverts_invalidInternalNodeHash() (gas: 50833) +MerkleTrie_Test:test_get_reverts_nonexistentKey1() (gas: 59694) +MerkleTrie_Test:test_get_reverts_nonexistentKey2() (gas: 23407) +MerkleTrie_Test:test_get_reverts_smallerPathThanKey1() (gas: 53502) +MerkleTrie_Test:test_get_reverts_smallerPathThanKey2() (gas: 54962) +MerkleTrie_Test:test_get_reverts_wrongKeyProof() (gas: 53870) +MerkleTrie_Test:test_get_reverts_zeroBranchValueLength() (gas: 43270) +MerkleTrie_Test:test_get_reverts_zeroLengthKey() (gas: 3655) +MerkleTrie_Test:test_get_validProofSucceeds1() (gas: 61667) +MerkleTrie_Test:test_get_validProofSucceeds10() (gas: 50572) +MerkleTrie_Test:test_get_validProofSucceeds2() (gas: 71557) +MerkleTrie_Test:test_get_validProofSucceeds3() (gas: 32827) +MerkleTrie_Test:test_get_validProofSucceeds4() (gas: 23623) +MerkleTrie_Test:test_get_validProofSucceeds5() (gas: 84306) +MerkleTrie_Test:test_get_validProofSucceeds6() (gas: 73039) +MerkleTrie_Test:test_get_validProofSucceeds7() (gas: 79674) +MerkleTrie_Test:test_get_validProofSucceeds8() (gas: 50528) +MerkleTrie_Test:test_get_validProofSucceeds9() (gas: 50549) OptimismMintableERC20_Test:test_bridge() (gas: 7599) OptimismMintableERC20_Test:test_burn() (gas: 51031) OptimismMintableERC20_Test:test_burnRevertsFromNotBridge() (gas: 11164) @@ -170,23 +180,23 @@ OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 10 OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15767) OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_success() (gas: 16010) OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_success() (gas: 180435) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 198517) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 200739) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 198543) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 200765) OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 39634) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 196193) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 194402) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 174437) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 234659) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 238957) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() (gas: 230626) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 333263) -OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 194807) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 196219) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 194532) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 174463) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 234789) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 238983) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() (gas: 230652) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 333289) +OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 194833) OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85539) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 137224) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 137250) OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 50754) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_success() (gas: 277238) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 190171) -OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_success() (gas: 180360) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_success() (gas: 277290) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 190197) +OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_success() (gas: 180386) OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17298) OptimismPortal_Test:test_OptimismPortalReceiveEth_success() (gas: 127483) OptimismPortal_Test:test_depositTransaction_NoValueContract_success() (gas: 76706) @@ -303,7 +313,7 @@ ResourceMetering_Test:test_updateTenEmptyBlocks() (gas: 20548) ResourceMetering_Test:test_updateTwoEmptyBlocks() (gas: 20594) ResourceMetering_Test:test_useMaxSucceeds() (gas: 8017123) ResourceMetering_Test:test_useMoreThanMaxReverts() (gas: 16045) -SafeCall_Test:test_safeCall(address,address,uint256,uint64,bytes) (runs: 256, μ: 43316, ~: 45640) +SafeCall_Test:test_safeCall(address,address,uint256,uint64,bytes) (runs: 256, μ: 43191, ~: 45640) Semver_Test:test_behindProxy() (gas: 506748) Semver_Test:test_version() (gas: 9373) SequencerFeeVault_Test:test_constructor() (gas: 5459) diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index 1387a606e95c7..316eb6927408f 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -10,3 +10,4 @@ src/contract-artifacts.ts tmp-artifacts deployments/mainnet-forked deploy-config/mainnet-forked.json +go-fuzz/fuzz diff --git a/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol b/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol index 13799f6af5862..3921d4d83a7ee 100644 --- a/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol +++ b/packages/contracts-bedrock/contracts/libraries/trie/MerkleTrie.sol @@ -90,6 +90,8 @@ library MerkleTrie { bytes[] memory _proof, bytes32 _root ) internal pure returns (bytes memory) { + require(_key.length > 0, "MerkleTrie: empty key"); + TrieNode[] memory proof = _parseProof(_proof); bytes memory key = Bytes.toNibbles(_key); bytes memory currentNodeID = abi.encodePacked(_root); diff --git a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol index a7f2e61768db8..cbbee84f1f969 100644 --- a/packages/contracts-bedrock/contracts/test/CommonTest.t.sol +++ b/packages/contracts-bedrock/contracts/test/CommonTest.t.sol @@ -129,10 +129,7 @@ contract L2OutputOracle_Initializer is CommonTest { vm.prank(multisig); proxy.upgradeToAndCall( address(oracleImpl), - abi.encodeCall( - L2OutputOracle.initialize, - (startingBlockNumber, startingTimestamp) - ) + abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp)) ); oracle = L2OutputOracle(address(proxy)); vm.label(address(oracle), "L2OutputOracle"); @@ -631,6 +628,25 @@ contract FFIInterface is Test { bytes memory result = vm.ffi(cmds); return abi.decode(result, (uint256, uint256)); } + + function getMerkleTrieFuzzCase(string memory variant) + external + returns ( + bytes32, + bytes memory, + bytes memory, + bytes[] memory + ) + { + string[] memory cmds = new string[](5); + cmds[0] = "./go-fuzz/fuzz"; + cmds[1] = "-m"; + cmds[2] = "trie"; + cmds[3] = "-v"; + cmds[4] = variant; + + return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[])); + } } // Used for testing a future upgrade beyond the current implementations. diff --git a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol index c33b870ca2e4e..d0f4041354c74 100644 --- a/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/contracts/test/L2OutputOracle.t.sol @@ -335,18 +335,12 @@ contract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer { function test_cannotInitProxy() external { vm.expectRevert("Initializable: contract is already initialized"); - L2OutputOracle(payable(proxy)).initialize( - startingBlockNumber, - startingTimestamp - ); + L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp); } function test_cannotInitImpl() external { vm.expectRevert("Initializable: contract is already initialized"); - L2OutputOracle(oracleImpl).initialize( - startingBlockNumber, - startingTimestamp - ); + L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp); } function test_upgrading() external { diff --git a/packages/contracts-bedrock/contracts/test/MerkleTrie.t.sol b/packages/contracts-bedrock/contracts/test/MerkleTrie.t.sol index 1e831839b7821..d9d1110d89399 100644 --- a/packages/contracts-bedrock/contracts/test/MerkleTrie.t.sol +++ b/packages/contracts-bedrock/contracts/test/MerkleTrie.t.sol @@ -5,59 +5,56 @@ import { CommonTest } from "./CommonTest.t.sol"; import { MerkleTrie } from "../libraries/trie/MerkleTrie.sol"; contract MerkleTrie_Test is CommonTest { + function setUp() public { + _setUp(); + } + function test_get_validProofSucceeds1() external { bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; bytes memory key = hex"6b6579326262"; bytes memory val = hex"6176616c32"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; - proof[1] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; + proof[ + 0 + ] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; + proof[ + 1 + ] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; proof[2] = hex"ca83206262856176616c32"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds2() external { bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; bytes memory key = hex"6b6579316161"; - bytes memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; + bytes + memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; - proof[1] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; - proof[2] = hex"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; - - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + proof[ + 0 + ] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; + proof[ + 1 + ] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; + proof[ + 2 + ] = hex"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; + + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds3() external { bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed; bytes memory key = hex"6b6579316161"; - bytes memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; + bytes + memory val = hex"303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; bytes[] memory proof = new bytes[](1); - proof[0] = hex"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; - - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + proof[ + 0 + ] = hex"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878"; + + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds4() external { @@ -67,33 +64,26 @@ contract MerkleTrie_Test is CommonTest { bytes[] memory proof = new bytes[](1); proof[0] = hex"ce87206b6579316161853031323334"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds5() external { bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89; bytes memory key = hex"6b657931"; - bytes memory val = hex"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; + bytes + memory val = hex"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; - proof[1] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; - proof[2] = hex"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; - - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + proof[ + 0 + ] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; + proof[ + 1 + ] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; + proof[ + 2 + ] = hex"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67"; + + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds6() external { @@ -101,18 +91,15 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"6b657932"; bytes memory val = hex"73686f7274"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; - proof[1] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; + proof[ + 0 + ] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; + proof[ + 1 + ] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; proof[2] = hex"df808080808080c9823262856176616c338080808080808080808573686f7274"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds7() external { @@ -120,18 +107,17 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"6b657933"; bytes memory val = hex"31323334353637383930313233343536373839303132333435363738393031"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; - proof[1] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; - proof[2] = hex"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031"; - - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + proof[ + 0 + ] = hex"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779"; + proof[ + 1 + ] = hex"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080"; + proof[ + 2 + ] = hex"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031"; + + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds8() external { @@ -143,14 +129,7 @@ contract MerkleTrie_Test is CommonTest { proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; proof[2] = hex"c22061"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds9() external { @@ -162,14 +141,7 @@ contract MerkleTrie_Test is CommonTest { proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; proof[2] = hex"c22062"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_validProofSucceeds10() external { @@ -181,44 +153,35 @@ contract MerkleTrie_Test is CommonTest { proof[1] = hex"d780c22061c22062c2206380808080808080808080808080"; proof[2] = hex"c22063"; - assertEq( - val, - MerkleTrie.get( - key, - proof, - root - ) - ); + assertEq(val, MerkleTrie.get(key, proof, root)); } function test_get_reverts_nonexistentKey1() external { bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; bytes memory key = hex"6b657932"; bytes[] memory proof = new bytes[](3); - proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; - proof[1] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; + proof[ + 0 + ] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; + proof[ + 1 + ] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; proof[2] = hex"ca83206262856176616c32"; vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_nonexistentKey2() external { bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f; bytes memory key = hex"616e7972616e646f6d6b6579"; bytes[] memory proof = new bytes[](1); - proof[0] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; + proof[ + 0 + ] = hex"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_wrongKeyProof() external { @@ -226,15 +189,13 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"6b6579316161"; bytes[] memory proof = new bytes[](3); proof[0] = hex"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f"; - proof[1] = hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; + proof[ + 1 + ] = hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; proof[2] = hex"d687206e6f746865728d33343938683472697568677765"; vm.expectRevert("MerkleTrie: invalid internal node hash"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_corruptedProof() external { @@ -242,17 +203,19 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"6b6579326262"; bytes[] memory proof = new bytes[](5); proof[0] = hex"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2"; - proof[1] = hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; - proof[2] = hex"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; - proof[3] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; + proof[ + 1 + ] = hex"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080"; + proof[ + 2 + ] = hex"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386"; + proof[ + 3 + ] = hex"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080"; proof[4] = hex"ca83206262856176616c32"; vm.expectRevert("RLPReader: decoded item type for list is not a list item"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_invalidDataRemainder() external { @@ -264,11 +227,7 @@ contract MerkleTrie_Test is CommonTest { proof[2] = hex"c32081aa000000000000000000000000000000"; vm.expectRevert("RLPReader: list item has an invalid data remainder"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_invalidInternalNodeHash() external { @@ -276,15 +235,13 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"aa"; bytes[] memory proof = new bytes[](3); proof[0] = hex"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157"; - proof[1] = hex"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080"; + proof[ + 1 + ] = hex"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080"; proof[2] = hex"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f"; vm.expectRevert("MerkleTrie: invalid internal node hash"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_zeroBranchValueLength() external { @@ -295,11 +252,7 @@ contract MerkleTrie_Test is CommonTest { proof[1] = hex"d98080808080808080808080c43b82aabbc43c82aacc80808080"; vm.expectRevert("MerkleTrie: value length must be greater than zero (branch)"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_zeroLengthKey() external { @@ -308,12 +261,8 @@ contract MerkleTrie_Test is CommonTest { bytes[] memory proof = new bytes[](1); proof[0] = hex"c78320f00082b443"; - vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - MerkleTrie.get( - key, - proof, - root - ); + vm.expectRevert("MerkleTrie: empty key"); + MerkleTrie.get(key, proof, root); } function test_get_reverts_smallerPathThanKey1() external { @@ -325,11 +274,7 @@ contract MerkleTrie_Test is CommonTest { proof[2] = hex"c582202381aa"; vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_smallerPathThanKey2() external { @@ -337,15 +282,13 @@ contract MerkleTrie_Test is CommonTest { bytes memory key = hex"aa"; bytes[] memory proof = new bytes[](3); proof[0] = hex"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905"; - proof[1] = hex"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080"; + proof[ + 1 + ] = hex"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080"; proof[2] = hex"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af"; vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); - MerkleTrie.get( - key, - proof, - root - ); + MerkleTrie.get(key, proof, root); } function test_get_reverts_extraProofElements() external { @@ -358,10 +301,121 @@ contract MerkleTrie_Test is CommonTest { proof[3] = hex"c32081aa"; vm.expectRevert("MerkleTrie: value node must be last node in proof (leaf)"); - MerkleTrie.get( - key, - proof, - root + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_validProofs_success(bytes4) external { + // Generate a test case with a valid proof of inclusion for the k/v pair in the trie. + (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi + .getMerkleTrieFuzzCase("valid"); + + // Assert that our expected value is equal to our actual value. + assertEq(val, MerkleTrie.get(key, proof, root)); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_invalidRoot_reverts(bytes4) external { + // Get a random test case with a valid trie / proof + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "valid" + ); + + bytes32 rootHash = keccak256(abi.encodePacked(root)); + vm.expectRevert("MerkleTrie: invalid root hash"); + MerkleTrie.get(key, proof, rootHash); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_extraProofElements_reverts(bytes4) external { + // Generate an invalid test case with an extra proof element attached to an otherwise + // valid proof of inclusion for the passed k/v. + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "extra_proof_elems" + ); + + vm.expectRevert("MerkleTrie: value node must be last node in proof (leaf)"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external { + // Generate an invalid test case where a long proof element is incorrect for the root. + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "invalid_large_internal_hash" + ); + + vm.expectRevert("MerkleTrie: invalid large internal hash"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external { + // Generate an invalid test case where a small proof element is incorrect for the root. + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "invalid_internal_node_hash" ); + + vm.expectRevert("MerkleTrie: invalid internal node hash"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_corruptedProof_reverts(bytes4) external { + // Generate an invalid test case where the proof is malformed. + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "corrupted_proof" + ); + + vm.expectRevert("RLPReader: decoded item type for list is not a list item"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_invalidDataRemainder_reverts(bytes4) external { + // Generate an invalid test case where a random element of the proof has more bytes than the + // length designates within the RLP list encoding. + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "invalid_data_remainder" + ); + + vm.expectRevert("RLPReader: list item has an invalid data remainder"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_prefixedValidKey_reverts(bytes4) external { + // Get a random test case with a valid trie / proof and a valid key that is prefixed + // with random bytes + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "prefixed_valid_key" + ); + + // Ambiguous revert check- all that we care is that it *does* fail. This case may + // fail within different branches. + vm.expectRevert(); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_emptyKey_reverts(bytes4) external { + // Get a random test case with a valid trie / proof and an empty key + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "empty_key" + ); + + vm.expectRevert("MerkleTrie: empty key"); + MerkleTrie.get(key, proof, root); + } + + /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored. + function testFuzz_get_partialProof_reverts(bytes4) external { + // Get a random test case with a valid trie / partially correct proof + (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase( + "partial_proof" + ); + + vm.expectRevert("MerkleTrie: ran out of proof elements"); + MerkleTrie.get(key, proof, root); } } diff --git a/packages/contracts-bedrock/go-fuzz/README.md b/packages/contracts-bedrock/go-fuzz/README.md new file mode 100644 index 0000000000000..5dfdb302d27be --- /dev/null +++ b/packages/contracts-bedrock/go-fuzz/README.md @@ -0,0 +1,29 @@ +# `go-fuzz` + +A lightweight input fuzzing utility used for testing various Bedrock contracts. + +
+├── go-fuzz
+│   ├── cmd: `go-fuzz`'s binary
+│   └── trie: Utility for generating random merkle trie roots / inclusion proofs
+
+ +## Usage + +To generate an abi-encoded fuzz case, pass in a mode via the `-m` flag as well as an optional variant via the `-v` flag. + +### Available Modes + +#### `trie` + +> **Note** +> Variant required for `trie` mode. + +| Variant | Description | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| `valid` | Generate a test case with a valid proof of inclusion for the k/v pair in the trie. | +| `extra_proof_elems` | Generate an invalid test case with an extra proof element attached to an otherwise valid proof of inclusion for the passed k/v. | +| `corrupted_proof` | Generate an invalid test case where the proof is malformed. | +| `invalid_data_remainder` | Generate an invalid test case where a random element of the proof has more bytes than the length designates within the RLP list encoding. | +| `invalid_large_internal_hash` | Generate an invalid test case where a long proof element is incorrect for the root. | +| `invalid_internal_node_hash` | Generate an invalid test case where a small proof element is incorrect for the root. | diff --git a/packages/contracts-bedrock/go-fuzz/cmd/fuzz.go b/packages/contracts-bedrock/go-fuzz/cmd/fuzz.go new file mode 100644 index 0000000000000..f6441bdf2cc97 --- /dev/null +++ b/packages/contracts-bedrock/go-fuzz/cmd/fuzz.go @@ -0,0 +1,31 @@ +package main + +import ( + "flag" + "log" + + t "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/go-fuzz/trie" +) + +// Mode enum +const ( + // Enables the `trie` fuzzer + trie string = "trie" +) + +func main() { + mode := flag.String("m", "", "Fuzzer mode") + variant := flag.String("v", "", "Mode variant") + flag.Parse() + + if len(*mode) < 1 { + log.Fatal("Must pass a mode for the fuzzer!") + } + + switch *mode { + case trie: + t.FuzzTrie(*variant) + default: + log.Fatal("Invalid mode!") + } +} diff --git a/packages/contracts-bedrock/go-fuzz/go.mod b/packages/contracts-bedrock/go-fuzz/go.mod new file mode 100644 index 0000000000000..fa8155c185073 --- /dev/null +++ b/packages/contracts-bedrock/go-fuzz/go.mod @@ -0,0 +1,26 @@ +module github.com/ethereum-optimism/optimism/packages/contracts-bedrock/go-fuzz + +go 1.19 + +require github.com/ethereum/go-ethereum v1.10.26 + +require ( + github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/VictoriaMetrics/fastcache v1.6.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/tsdb v0.7.1 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tklauser/go-sysconf v0.3.5 // indirect + github.com/tklauser/numcpus v0.2.2 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect +) diff --git a/packages/contracts-bedrock/go-fuzz/go.sum b/packages/contracts-bedrock/go-fuzz/go.sum new file mode 100644 index 0000000000000..8be6ece524dd9 --- /dev/null +++ b/packages/contracts-bedrock/go-fuzz/go.sum @@ -0,0 +1,141 @@ +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= +github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/packages/contracts-bedrock/go-fuzz/trie/trie.go b/packages/contracts-bedrock/go-fuzz/trie/trie.go new file mode 100644 index 0000000000000..a850ea70e765a --- /dev/null +++ b/packages/contracts-bedrock/go-fuzz/trie/trie.go @@ -0,0 +1,248 @@ +package trie + +import ( + "crypto/rand" + "fmt" + "log" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +// Variant enum +const ( + // Generate a test case with a valid proof of inclusion for the k/v pair in the trie. + valid string = "valid" + // Generate an invalid test case with an extra proof element attached to an otherwise + // valid proof of inclusion for the passed k/v. + extraProofElems = "extra_proof_elems" + // Generate an invalid test case where the proof is malformed. + corruptedProof = "corrupted_proof" + // Generate an invalid test case where a random element of the proof has more bytes than the + // length designates within the RLP list encoding. + invalidDataRemainder = "invalid_data_remainder" + // Generate an invalid test case where a long proof element is incorrect for the root. + invalidLargeInternalHash = "invalid_large_internal_hash" + // Generate an invalid test case where a small proof element is incorrect for the root. + invalidInternalNodeHash = "invalid_internal_node_hash" + // Generate a valid test case with a key that has been given a random prefix + prefixedValidKey = "prefixed_valid_key" + // Generate a valid test case with a proof of inclusion for an empty key. + emptyKey = "empty_key" + // Generate an invalid test case with a partially correct proof + partialProof = "partial_proof" +) + +// Generate an abi-encoded `trieTestCase` of a specified variant +func FuzzTrie(variant string) { + if len(variant) < 1 { + log.Fatal("Must pass a variant to the trie fuzzer!") + } + + var testCase trieTestCase + switch variant { + case valid: + testCase = genTrieTestCase(false) + break + case extraProofElems: + testCase = genTrieTestCase(false) + // Duplicate the last element of the proof + testCase.Proof = append(testCase.Proof, [][]byte{testCase.Proof[len(testCase.Proof)-1]}...) + break + case corruptedProof: + testCase = genTrieTestCase(false) + + // Re-encode a random element within the proof + idx := randRange(0, int64(len(testCase.Proof))) + encoded, _ := rlp.EncodeToBytes(testCase.Proof[idx]) + testCase.Proof[idx] = encoded + break + case invalidDataRemainder: + testCase = genTrieTestCase(false) + + // Alter true length of random proof element by appending random bytes + // Do not update the encoded length + idx := randRange(0, int64(len(testCase.Proof))) + bytes := make([]byte, randRange(1, 512)) + rand.Read(bytes) + testCase.Proof[idx] = append(testCase.Proof[idx], bytes...) + break + case invalidLargeInternalHash: + testCase = genTrieTestCase(false) + + // Clobber 4 bytes within a list element of a random proof element + // TODO: Improve this by decoding the proof elem and choosing random + // bytes to overwrite. + idx := randRange(1, int64(len(testCase.Proof))) + b := make([]byte, 4) + rand.Read(b) + testCase.Proof[idx] = append( + testCase.Proof[idx][:20], + append( + b, + testCase.Proof[idx][24:]..., + )..., + ) + + break + case invalidInternalNodeHash: + testCase = genTrieTestCase(false) + // Assign the last proof element to an encoded list containing a + // random 29 byte value + b := make([]byte, 29) + rand.Read(b) + e, _ := rlp.EncodeToBytes(b) + testCase.Proof[len(testCase.Proof)-1] = append([]byte{0xc0 + 30}, e...) + case prefixedValidKey: + testCase = genTrieTestCase(false) + + bytes := make([]byte, randRange(1, 16)) + testCase.Key = append(bytes, testCase.Key...) + case emptyKey: + testCase = genTrieTestCase(true) + case partialProof: + testCase = genTrieTestCase(false) + + // Cut the proof in half + proofLen := len(testCase.Proof) + newProof := make([][]byte, proofLen/2) + for i := 0; i < proofLen/2; i++ { + newProof[i] = testCase.Proof[i] + } + + testCase.Proof = newProof + default: + log.Fatal("Invalid variant passed to trie fuzzer!") + } + + // Print encoded test case with no newline so that foundry's FFI can read the output + fmt.Print(testCase.AbiEncode()) +} + +// Generate a random test case for Bedrock's MerkleTrie verifier. +func genTrieTestCase(selectEmptyKey bool) trieTestCase { + // Create an empty merkle trie + memdb := memorydb.New() + randTrie := trie.NewEmpty(trie.NewDatabase(memdb)) + + // Get a random number of elements to put into the trie + randN := randRange(2, 1024) + // Get a random key/value pair to generate a proof of inclusion for + randSelect := randRange(0, randN) + + // Create a fixed-length key as well as a randomly-sized value + // We create these out of the loop to reduce mem allocations. + randKey := make([]byte, 32) + randValue := make([]byte, randRange(2, 1024)) + + // Randomly selected key/value for proof generation + var key []byte + var value []byte + + // Add `randN` elements to the trie + for i := int64(0); i < randN; i++ { + // Randomize the contents of `randKey` and `randValue` + rand.Read(randKey) + rand.Read(randValue) + + // Clear the selected key if `selectEmptyKey` is true + if i == randSelect && selectEmptyKey { + randKey = make([]byte, 0) + } + + // Insert the random k/v pair into the trie + if err := randTrie.TryUpdate(randKey, randValue); err != nil { + log.Fatal("Error adding key-value pair to trie") + } + + // If this is our randomly selected k/v pair, store it in `key` & `value` + if i == randSelect { + key = randKey + value = randValue + } + } + + // Generate proof for `key`'s inclusion in our trie + var proof proofList + if err := randTrie.Prove(key, 0, &proof); err != nil { + log.Fatal("Error creating proof for randomly selected key's inclusion in generated trie") + } + + // Create our test case with the data collected + testCase := trieTestCase{ + Root: randTrie.Hash(), + Key: key, + Value: value, + Proof: proof, + } + + return testCase +} + +// Represents a test case for bedrock's `MerkleTrie.sol` +type trieTestCase struct { + Root common.Hash + Key []byte + Value []byte + Proof [][]byte +} + +// Tuple type to encode `TrieTestCase` +var ( + trieTestCaseTuple, _ = abi.NewType("tuple", "TrieTestCase", []abi.ArgumentMarshaling{ + {Name: "root", Type: "bytes32"}, + {Name: "key", Type: "bytes"}, + {Name: "value", Type: "bytes"}, + {Name: "proof", Type: "bytes[]"}, + }) + + encoder = abi.Arguments{ + {Type: trieTestCaseTuple}, + } +) + +// Encodes the trieTestCase as the `trieTestCaseTuple`. +func (t *trieTestCase) AbiEncode() string { + // Encode the contents of the struct as a tuple + packed, err := encoder.Pack(&t) + if err != nil { + log.Fatalf("Error packing TrieTestCase: %v", err) + } + + // Remove the pointer and encode the packed bytes as a hex string + return hexutil.Encode(packed[32:]) +} + +// Helper that generates a cryptographically secure random 64-bit integer +// between the range [min, max) +func randRange(min int64, max int64) int64 { + r, err := rand.Int(rand.Reader, new(big.Int).Sub(new(big.Int).SetInt64(max), new(big.Int).SetInt64(min))) + if err != nil { + log.Fatal("Failed to generate random number within bounds") + } + + return (new(big.Int).Add(r, new(big.Int).SetInt64(min))).Int64() +} + +// Represents a range between two 64-bit integers +type intRange struct { + min int64 + max int64 +} + +// Custom type to write the generated proof to +type proofList [][]byte + +func (n *proofList) Put(key []byte, value []byte) error { + *n = append(*n, value) + return nil +} + +func (n *proofList) Delete(key []byte) error { + panic("not supported") +} diff --git a/packages/contracts-bedrock/package.json b/packages/contracts-bedrock/package.json index 4d8e40be13196..e86b71b5c6e58 100644 --- a/packages/contracts-bedrock/package.json +++ b/packages/contracts-bedrock/package.json @@ -17,19 +17,20 @@ "build:forge": "forge build", "build:with-metadata": "hardhat clean && FOUNDRY_PROFILE=echidna hardhat compile", "build:differential": "tsc scripts/differential-testing.ts --outDir dist --moduleResolution node --esModuleInterop", + "build:scripts": "go build -o go-fuzz go-fuzz/cmd/fuzz.go", "prebuild": "yarn ts-node scripts/verify-foundry-install.ts", - "build": "hardhat compile && yarn autogen:artifacts && yarn build:ts && yarn typechain", + "build": "hardhat compile && yarn autogen:artifacts && yarn build:ts && yarn typechain && yarn build:scripts", "build:ts": "tsc -p tsconfig.json", "autogen:artifacts": "ts-node scripts/generate-artifacts.ts", "deploy": "hardhat deploy", - "test": "yarn build:differential && forge test", - "coverage": "yarn build:differential && forge coverage", - "coverage:lcov": "yarn build:differential && forge coverage --report lcov", - "gas-snapshot": "yarn build:differential && forge snapshot --no-match-test 'differential|fuzz'", + "test": "yarn build:differential && yarn build:scripts && forge test", + "coverage": "yarn build:differential && yarn build:scripts && forge coverage", + "coverage:lcov": "yarn build:differential && yarn build:scripts && forge coverage --report lcov", + "gas-snapshot": "yarn build:differential && yarn build:scripts && forge snapshot --no-match-test 'differential|fuzz'", "storage-snapshot": "./scripts/storage-snapshot.sh", "validate-spacers": "hardhat validate-spacers", "slither": "./scripts/slither.sh", - "clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./src/contract-artifacts.ts", + "clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./src/contract-artifacts.ts ./go-fuzz/fuzz", "lint:ts:check": "eslint . --max-warnings=0", "lint:contracts:check": "yarn solhint -f table 'contracts/**/*.sol'", "lint:check": "yarn lint:contracts:check && yarn lint:ts:check",