├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── CI-plugin.yml │ ├── CI.yml │ ├── PR.yml │ ├── optimism-testing.yml │ ├── release.yml │ ├── solc │ └── upgrade-dependencies.yaml ├── .gitignore ├── .gitmodules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTION.md ├── LICENSE ├── README.md ├── docs ├── Makefile ├── pml │ └── ensBuilder.pml ├── release-notes │ ├── 2.0.0.md │ ├── 2.0.1.md │ ├── 2.0.10.md │ ├── 2.0.11.md │ ├── 2.0.12.md │ ├── 2.0.13.md │ ├── 2.0.14.md │ ├── 2.0.15.md │ ├── 2.0.16.md │ ├── 2.0.2.md │ ├── 2.0.3.md │ ├── 2.0.4.md │ ├── 2.0.5.md │ ├── 2.0.6.md │ ├── 2.0.7.md │ ├── 2.0.8.md │ ├── 2.0.9.md │ ├── 2.1.0.md │ ├── 2.1.1.md │ ├── 2.1.2.md │ ├── 2.2.0.md │ ├── 2.3.0.md │ ├── 2.3.1.md │ ├── 2.3.2.md │ ├── 2.4.0.md │ ├── 2.4.1.md │ ├── 2.5.0.md │ ├── 3.0.0-beta.1.md │ ├── 3.0.0-beta.2.md │ ├── 3.0.0-beta.3.md │ ├── 3.0.0.md │ ├── 3.0.1.md │ ├── 3.0.2.md │ ├── 3.0.3 │ ├── 3.1.0.md │ ├── 3.1.1.md │ ├── 3.1.2.md │ ├── 3.2.0.md │ ├── 3.2.1.md │ └── 3.2.2.md ├── requirements.txt └── source │ ├── _static │ ├── .gitkeep │ ├── custom.css │ ├── favicon.ico │ └── waffle-logo-square.svg │ ├── basic-testing.rst │ ├── compilation.rst │ ├── conf.py │ ├── configuration.rst │ ├── ens.rst │ ├── fixtures.rst │ ├── getting-started.rst │ ├── index.rst │ ├── logo.png │ ├── matchers.rst │ ├── migration-guides.rst │ └── mock-contract.rst ├── examples ├── .eslintrc.example.js ├── basic │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ └── BasicToken.sol │ ├── test │ │ ├── BasicToken.test.ts │ │ └── mocha.opts │ ├── tsconfig.json │ └── waffle.json ├── called-on-contract │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ └── AmIRichAlready.sol │ ├── test │ │ ├── AmIRichAlready.test.ts │ │ └── mocha.opts │ ├── tsconfig.json │ └── waffle.json ├── change-balance │ ├── .eslintrc.js │ ├── package.json │ ├── test │ │ ├── ChangeBalance.test.ts │ │ └── mocha.opts │ └── tsconfig.json ├── dynamic-mocking-and-testing-calls │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ └── AmIRichAlready.sol │ ├── test │ │ ├── AmIRichAlready.test.ts │ │ └── mocha.opts │ ├── tsconfig.json │ └── waffle.json ├── ens │ ├── .eslintrc.js │ ├── package.json │ ├── test │ │ ├── ENS.test.ts │ │ └── mocha.opts │ └── tsconfig.json ├── mock-contracts │ ├── .eslintrc.js │ ├── package.json │ ├── src │ │ └── AmIRichAlready.sol │ ├── test │ │ ├── AmIRichAlready.test.ts │ │ └── mocha.opts │ ├── tsconfig.json │ └── waffle.json └── typechain-example │ ├── .eslintrc.js │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ └── BasicToken.sol │ ├── test │ ├── BasicToken.test.ts │ └── mocha.opts │ ├── tsconfig.json │ └── waffle.json ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts └── dev-version.sh ├── tsconfig.json ├── waffle-chai ├── .eslintrc.js ├── .mocharc.js ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── src │ ├── call-promise.ts │ ├── index.ts │ ├── log.ts │ ├── matchers │ │ ├── README.md │ │ ├── bigNumber.ts │ │ ├── calledOnContract │ │ │ ├── assertions.ts │ │ │ ├── calledOnContract.ts │ │ │ ├── calledOnContractValidators.ts │ │ │ ├── calledOnContractWith.ts │ │ │ ├── error.ts │ │ │ └── utils.ts │ │ ├── changeBalance.ts │ │ ├── changeBalances.ts │ │ ├── changeEtherBalance.ts │ │ ├── changeEtherBalances.ts │ │ ├── changeTokenBalance.ts │ │ ├── changeTokenBalances.ts │ │ ├── emit.ts │ │ ├── hexEqual.ts │ │ ├── misc │ │ │ ├── account.ts │ │ │ ├── balance.ts │ │ │ ├── struct.ts │ │ │ └── transaction.ts │ │ ├── properAddress.ts │ │ ├── properHex.ts │ │ ├── properPrivateKey.ts │ │ ├── reverted.ts │ │ ├── revertedWith.ts │ │ ├── withArgs.ts │ │ └── withNamedArgs.ts │ └── types.ts ├── test │ ├── contracts │ │ ├── Calls.ts │ │ ├── Complex.ts │ │ ├── Events.ts │ │ ├── EventsProxy.ts │ │ ├── Matchers.ts │ │ └── MockToken.ts │ ├── index.ts │ ├── matchers │ │ ├── MockProviderCases.ts │ │ ├── bigNumber.test.ts │ │ ├── calledOnContract │ │ │ ├── calledOnContract.test.ts │ │ │ ├── calledOnContractTest.ts │ │ │ ├── calledOnContractValidators.test.ts │ │ │ ├── calledOnContractValidatorsTest.ts │ │ │ ├── calledOnContractWith.test.ts │ │ │ └── calledOnContractWithTest.ts │ │ ├── chaining.test.ts │ │ ├── chainingTest.ts │ │ ├── changeBalance.test.ts │ │ ├── changeBalances.test.ts │ │ ├── changeEtherBalance.test.ts │ │ ├── changeEtherBalanceTest.ts │ │ ├── changeEtherBalances.test.ts │ │ ├── changeEtherBalancesTest.ts │ │ ├── changeTokenBalance.test.ts │ │ ├── changeTokenBalanceTest.ts │ │ ├── changeTokenBalances.test.ts │ │ ├── changeTokenBalancesTest.ts │ │ ├── constants.ts │ │ ├── events.test.ts │ │ ├── eventsTest.ts │ │ ├── hexEqual.test.ts │ │ ├── misc.test.ts │ │ ├── reverted.test.ts │ │ ├── revertedTest.ts │ │ └── revertedWithTest.ts │ └── test-setup.ts ├── tsconfig.build.json └── tsconfig.json ├── waffle-cli ├── .eslintrc.js ├── .gitignore ├── .mocharc.js ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin │ └── waffle ├── buildTestContracts.ts ├── package.json ├── src │ ├── ContractJSON.ts │ ├── cli.ts │ ├── deployContract.ts │ └── index.ts ├── test │ ├── deployContract.ts │ ├── deployTypedContract.ts │ ├── example │ │ ├── example.ts │ │ └── fixtures-example.ts │ ├── index.ts │ └── projects │ │ └── example │ │ ├── BasicToken.sol │ │ ├── Check.sol │ │ ├── ERC20Basic.sol │ │ ├── LibraryConsumer.sol │ │ ├── MyLibrary.sol │ │ ├── SafeMath.sol │ │ ├── mock │ │ └── BasicTokenMock.sol │ │ └── readme.md ├── tsconfig.build.json └── tsconfig.json ├── waffle-compiler ├── .eslintrc.js ├── .gitignore ├── .mocharc.js ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── src │ ├── compileDockerSolc.ts │ ├── compileDockerVyper.ts │ ├── compileNativeSolc.ts │ ├── compileSolcjs.ts │ ├── compiler.ts │ ├── compilerInput.ts │ ├── config │ │ ├── config.ts │ │ ├── defaultConfig.ts │ │ ├── index.ts │ │ ├── inputToConfig.ts │ │ └── loadConfig.ts │ ├── executeCommand.ts │ ├── findImports.ts │ ├── findInputs.ts │ ├── flattener.ts │ ├── generateTypes.ts │ ├── getCompileFunction.ts │ ├── getHumanReadableAbi.ts │ ├── index.ts │ ├── link.ts │ ├── saveOutput.ts │ ├── shims │ │ └── solc.d.ts │ └── utils.ts ├── test │ ├── compiler │ │ ├── compileWithTypes.ts │ │ ├── compiler.ts │ │ ├── compilerOptions.ts │ │ ├── defaultConfigFile.ts │ │ ├── e2e.ts │ │ ├── e2e_errors.ts │ │ ├── e2e_vyper.ts │ │ ├── findImports.ts │ │ ├── findInputs.ts │ │ ├── humanReadableAbi.ts │ │ ├── outputType.ts │ │ └── wrappers │ │ │ ├── compileDocker.ts │ │ │ ├── compileNative.ts │ │ │ ├── compileSolcjs.ts │ │ │ ├── compilerOutput.json │ │ │ └── saveOutput.ts │ ├── config.ts │ ├── flattener │ │ ├── expectedFlattenChild.sol │ │ ├── flattener.ts │ │ └── testSource │ │ │ ├── child.sol │ │ │ ├── cycle1.sol │ │ │ ├── cycle2.sol │ │ │ ├── directives.sol │ │ │ ├── directivesImport.sol │ │ │ └── parent.sol │ ├── index.ts │ ├── link.ts │ ├── projects │ │ ├── compilerOptions │ │ │ ├── config.json │ │ │ ├── config_docker.json │ │ │ ├── config_native.json │ │ │ └── contracts │ │ │ │ └── Constantinople.sol │ │ ├── defaultConfigFile │ │ │ ├── contracts │ │ │ │ └── AmIRichAlready.sol │ │ │ └── waffle.json │ │ ├── example │ │ │ ├── BasicToken.sol │ │ │ ├── Check.sol │ │ │ ├── ERC20Basic.sol │ │ │ ├── LibraryConsumer.sol │ │ │ ├── MyLibrary.sol │ │ │ ├── SafeMath.sol │ │ │ ├── mock │ │ │ │ └── BasicTokenMock.sol │ │ │ └── readme.md │ │ ├── humanReadableAbi │ │ │ ├── config.json │ │ │ ├── config2.json │ │ │ └── contracts │ │ │ │ └── MyContract.sol │ │ ├── insideOut │ │ │ ├── main │ │ │ │ ├── config_docker.json │ │ │ │ └── contracts │ │ │ │ │ ├── Custom.sol │ │ │ │ │ ├── MyLibrary.sol │ │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── invalidContracts │ │ │ ├── config_docker.json │ │ │ ├── config_native.json │ │ │ ├── config_solcjs.json │ │ │ └── invalid.sol │ │ ├── outputType │ │ │ ├── config-minimal-humanReadableAbi.json │ │ │ ├── config-minimal.json │ │ │ └── contracts │ │ │ │ └── Constantinople.sol │ │ ├── solidity4 │ │ │ ├── config_docker.json │ │ │ ├── config_solcjs.json │ │ │ ├── config_solcjs_commit.json │ │ │ ├── custom_contracts │ │ │ │ ├── Custom.sol │ │ │ │ ├── MyLibrary.sol │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── custom_node_modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── solidity5 │ │ │ ├── config_commonjs.js │ │ │ ├── config_docker.json │ │ │ ├── config_klab.json │ │ │ ├── config_native.json │ │ │ ├── config_promise.js │ │ │ ├── config_solcjs.json │ │ │ ├── config_solcjs_commit.json │ │ │ ├── custom_contracts │ │ │ │ ├── Custom.sol │ │ │ │ ├── MyLibrary.sol │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── custom_node_modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── solidity6 │ │ │ ├── config_docker.json │ │ │ ├── config_solcjs.json │ │ │ ├── config_solcjs_commit.json │ │ │ ├── custom_contracts │ │ │ │ ├── Custom.sol │ │ │ │ ├── MyLibrary.sol │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── custom_node_modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── solidity7 │ │ │ ├── config_docker.json │ │ │ ├── config_solcjs.json │ │ │ ├── config_solcjs_commit.json │ │ │ ├── custom_contracts │ │ │ │ ├── Custom.sol │ │ │ │ ├── MyLibrary.sol │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── custom_node_modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── solidity8 │ │ │ ├── config_docker.json │ │ │ ├── config_solcjs.json │ │ │ ├── config_solcjs_commit.json │ │ │ ├── custom_contracts │ │ │ │ ├── Custom.sol │ │ │ │ ├── MyLibrary.sol │ │ │ │ └── sub │ │ │ │ │ ├── One.sol │ │ │ │ │ └── Two.sol │ │ │ └── custom_node_modules │ │ │ │ └── openzeppelin-solidity │ │ │ │ ├── CustomSafeMath.sol │ │ │ │ └── sub │ │ │ │ └── ERC20.sol │ │ ├── typechain │ │ │ ├── config.json │ │ │ └── contracts │ │ │ │ ├── Constantinople.json │ │ │ │ └── Constantinople.sol │ │ └── vyper0.1 │ │ │ ├── config_vyper_0b15.json │ │ │ ├── config_vyper_0b17.json │ │ │ └── custom_contracts │ │ │ └── Custom.vy │ ├── typegeneration │ │ └── typechain.ts │ └── utils.ts ├── tsconfig.build.json └── tsconfig.json ├── waffle-e2e ├── .eslintrc.js ├── .gitignore ├── .mocharc.js ├── CHANGELOG.md ├── buildTestContracts.ts ├── package.json ├── src │ └── HelloContract.sol ├── test │ └── index.ts └── tsconfig.json ├── waffle-ens ├── .eslintrc.js ├── .mocharc.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build-artifacts.js ├── package.json ├── src │ ├── ENS.ts │ ├── contracts.js │ ├── errors.ts │ ├── index.ts │ ├── types.d.ts │ └── utils.ts ├── test │ ├── ENS.test.ts │ ├── utils.test.ts │ └── utils.ts ├── tsconfig.build.json └── tsconfig.json ├── waffle-hardhat ├── .eslintrc.js ├── .mocharc.js ├── CHANGELOG.md ├── README.md ├── contracts │ └── CustomError.sol ├── hardhat.config.ts ├── package.json ├── test │ ├── calledOnContract │ │ ├── calledOnContract.test.ts │ │ ├── calledOnContractValidators.test.ts │ │ └── calledOnContractWith.test.ts │ ├── chaining.test.ts │ ├── changeEtherBalance.test.ts │ ├── changeEtherBalances.test.ts │ ├── changeTokenBalance.test.ts │ ├── changeTokenBalances.test.ts │ ├── constants.ts │ ├── events.test.ts │ ├── mockContract.test.ts │ ├── reverted.test.ts │ └── test-setup.ts └── tsconfig.json ├── waffle-mock-contract ├── .eslintrc.js ├── .gitignore ├── .mocharc.js ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── compile.ts ├── package.json ├── src │ ├── Doppelganger.sol │ └── index.ts ├── test │ ├── amirichalready.test.ts │ ├── contract.test.ts │ ├── direct.test.ts │ ├── directTest.ts │ ├── etherForward.test.ts │ ├── helpers │ │ ├── buildTestContracts.ts │ │ └── contracts │ │ │ ├── AmIRichAlready.sol │ │ │ ├── Counter.sol │ │ │ ├── CounterOverloaded.sol │ │ │ ├── EtherForward.sol │ │ │ └── Proxy.sol │ ├── mockChaining.test.ts │ ├── proxied.test.ts │ └── proxiedTest.ts ├── tsconfig.build.json └── tsconfig.json ├── waffle-optimism ├── .eslintrc.js ├── .mocharc.js ├── CHANGELOG.md ├── package.json ├── src │ ├── index.ts │ └── provider.ts ├── test │ ├── chaining.test.ts │ ├── changeEtherBalance.test.ts │ ├── changeEtherBalances.test.ts │ ├── changeTokenBalance.test.ts │ ├── changeTokenBalances.test.ts │ ├── events.test.ts │ ├── reverted.test.ts │ ├── test-setup.ts │ └── utils │ │ ├── getTxGasFees.ts │ │ └── index.ts ├── tsconfig.build.json └── tsconfig.json └── waffle-provider ├── .eslintrc.js ├── .mocharc.js ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── patches └── ganache+7.0.3.patch ├── src ├── CallHistory.ts ├── MockProvider.ts ├── defaultAccounts.ts ├── fixtures.ts ├── index.ts ├── log.ts ├── revertString.ts └── test-provider.ts ├── test ├── BasicToken.ts ├── Caller.ts ├── MockProvider.test.ts ├── MockProviderCases.ts ├── MockProviderWallets.test.ts ├── callHistory.test.ts ├── fixtures.ts ├── index.ts └── revertString.test.ts ├── tsconfig.build.json └── tsconfig.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.4.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "restricted", 7 | "baseBranch": "master", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [] 10 | } 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior, or a link to a repository if public. 15 | Snippets of code are welcome. 16 | 17 | **Software versions** 18 | - `ethereum-waffle` version 19 | - `@nomiclabs/hardhat-waffle` version, if using 20 | - `@nomiclabs/hardhat-ethers` version, if using 21 | - `hardhat` version, if using 22 | - Package manager (yarn, npm, or pnpm?) 23 | - Node version (`node --version`) 24 | - Solidity version, if relevant 25 | 26 | **Additional context** 27 | 28 | - Add any other context about the problem here 29 | - Include screenshots if applicable 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Feature Request]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/PR.yml: -------------------------------------------------------------------------------- 1 | name: PR Naming 2 | on: 3 | pull_request: 4 | types: [opened, edited, synchronize, reopened] 5 | jobs: 6 | emoji: 7 | name: Pull Request should start from emoji 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: deepakputhraya/action-pr-title@v1.0.2 11 | with: 12 | # Check if first character is an emoji, regex borrowed from https://medium.com/reactnative/emojis-in-javascript-f693d0eb79fb#.enomgcu63 13 | regex: '^(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])' 14 | github_token: ${{ github.token }} 15 | capitalised: 16 | name: Pull Request name should start from Capital letter with space 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: deepakputhraya/action-pr-title@v1.0.2 20 | with: 21 | regex: '^[^a-z]* [A-Z]' 22 | github_token: ${{ github.token }} 23 | -------------------------------------------------------------------------------- /.github/workflows/optimism-testing.yml: -------------------------------------------------------------------------------- 1 | name: Optimism testing 2 | 3 | on: 4 | push: 5 | branches: 6 | - changeset-release/* 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | # test against a known version and a current master 13 | OPTIMISM_GIT_HEAD: ["7abde925dccb57bac26661f22906686ff7e23ad0", "master"] 14 | steps: 15 | - uses: actions/checkout@v2 16 | with: 17 | fetch-depth: 0 18 | - uses: pnpm/action-setup@v2 19 | with: 20 | version: 6.32.4 21 | - name: Setup Node.js 16.x 22 | uses: actions/setup-node@v3.0.0 23 | with: 24 | node-version: 16.x 25 | - name: Build project 26 | run: | 27 | pnpm install 28 | pnpm build 29 | - name: Setup optimism node 30 | run: | 31 | cd .. 32 | git clone https://github.com/ethereum-optimism/optimism.git 33 | cd optimism/ops 34 | git checkout ${{ matrix.OPTIMISM_GIT_HEAD }} 35 | docker-compose pull 36 | docker-compose up & 37 | scripts/wait-for-sequencer.sh && echo "System is ready to accept transactions" 38 | - name: Test optimism 39 | run: | 40 | cd waffle-optimism 41 | pnpm run test:optimism 42 | -------------------------------------------------------------------------------- /.github/workflows/solc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker run -i ethereum/solc:0.5.15 $@ 3 | -------------------------------------------------------------------------------- /.github/workflows/upgrade-dependencies.yaml: -------------------------------------------------------------------------------- 1 | name: Upgrade dependencies 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | # every 1st and 16th of the month at 3am UTC 6 | - cron: "0 3 1,16 * *" 7 | jobs: 8 | upgrade: 9 | name: Upgrade dependencies 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 15 12 | steps: 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: 16.1 16 | - run: npm install -g npm-check-updates@^16.3.2 17 | - name: Upgrade dependencies 18 | uses: technote-space/create-pr-action@v2 19 | with: 20 | GITHUB_TOKEN: ${{ secrets. GH_BOT_TOKEN }} 21 | EXECUTE_COMMANDS: | 22 | cd waffle-provider 23 | ncu ganache --deep -u 24 | ncu solc --deep -u 25 | pnpm install --strict-peer-dependencies=false 26 | COMMIT_MESSAGE: "🤖 Upgrade dependencies" 27 | COMMIT_NAME: "truefibot" 28 | COMMIT_EMAIL: "truebot.github@trusttoken.com" 29 | PR_BRANCH_NAME: "chore-upgrade-dependencies-${PR_ID}" 30 | PR_TITLE: "🤖 Upgrade dependencies" 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | yarn-error.log 4 | /docs/build 5 | /docs/env 6 | .idea 7 | out 8 | docs/venv 9 | build 10 | cache 11 | 12 | # Auto-generated typechain files 13 | typechain 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hardhat-waffle-plugin"] 2 | path = hardhat-waffle-plugin 3 | url = https://github.com/NomicFoundation/hardhat-waffle 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ./waffle-cli/README.md -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = dist 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Runs "make html" in a loop every 3 seconds. 18 | # Useful for writing documentation. 19 | watch: 20 | while true; do make html -s; sleep 3; done 21 | 22 | # Catch-all target: route all unknown targets to Sphinx using the new 23 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 24 | %: Makefile 25 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 26 | -------------------------------------------------------------------------------- /docs/pml/ensBuilder.pml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | title ENSBuilder 4 | 5 | actor User 6 | participant ENS 7 | participant Resolver 8 | participant EthRegistrar 9 | participant FIFSRegistrar2 10 | 11 | == Get resolver == 12 | User -> ENS: resolver('eth') 13 | 14 | == Get registrar == 15 | User -> ENS: owner('eth') 16 | 17 | == builder.createTopLevelDomain('eth') == 18 | User -> EthRegistrar: construtor(ens, 'eth') 19 | User -> ENS: setSubnodeOwner(HashZero, 'ethworks.eth', ethRegistrar) 20 | 21 | == builder.createDomain('ethworks.eth') == 22 | User -> ENS: owner('eth') 23 | User -> ENS: setResolver(namehash('ethworks.eth'), resolver) 24 | User -> FIFSRegistrar2: construtor(ens, 'ethworks.eth') 25 | User -> ENS: setOwner(namehash('ethworks.eth'), FIFSRegistrar2) 26 | 27 | == buidler.setAddress('vald.ethworks.eth', '0x99..99') == 28 | User -> ENS: owner('ethworks.eth') 29 | User -> FIFSRegistrar2: register(namehash('vlad.ethworks.eth'), wallet) 30 | User -> ENS: setResolver('vlad.ethworks.eth', resolver) 31 | User -> Resolver: addr('vald.ethworks.eth', '0x99..99') 32 | 33 | @enduml 34 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.1.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | This release introduces minor fixes and functionalities. 3 | 4 | ## Windows support 5 | Thanks to the work of [@yaram](https://github.com/yaram) Waffle should now work on windows. 6 | 7 | ## Configurable allowedPaths for native solc compilation 8 | Waffle configuration file has now new field: `allowedPaths`. It allows to adding extra `--allow-paths` for natvie solc compiler. That might be required to make Waffle work with monorepos using [lerna](https://lernajs.io/). 9 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.10.md: -------------------------------------------------------------------------------- 1 | # Summary 2.0.10 2 | 3 | Add support for generating KLAB (a formal verification tool for Solidity, see: https://github.com/dapphub/klab) 4 | friendly compilation output. 5 | 6 | An example of full KLAB friendly config file is the following: 7 | 8 | ``` 9 | module.exports = { 10 | compiler: process.env.WAFFLE_COMPILER, 11 | legacyOutput: true, 12 | outputType: 'all', 13 | compilerOptions: { 14 | outputSelection: { 15 | "*": { 16 | "*": [ "evm.bytecode.object", "evm.deployedBytecode.object", 17 | "abi" , 18 | "evm.bytecode.sourceMap", "evm.deployedBytecode.sourceMap" ], 19 | 20 | "": [ "ast" ] 21 | }, 22 | } 23 | } 24 | }; 25 | ``` 26 | 27 | For details, see updated appropriate documentation file. 28 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.11.md: -------------------------------------------------------------------------------- 1 | This release contains minor bug fixes: 2 | * Changing ganache to 2.5.5 3 | * Add tests, covering fixture bug from ganache 2.4.0, added (#103) -------------------------------------------------------------------------------- /docs/release-notes/2.0.12.md: -------------------------------------------------------------------------------- 1 | This release contains minor update and a bug fix: 2 | * Fix fixtures interfering with each other 3 | * Update ganache 2.5.5 -> 2.5.6-beta 4 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.13.md: -------------------------------------------------------------------------------- 1 | This release updates dependencies: 2 | * ganache-core: 2.5.6-beta.0 -> ^2.5.7 3 | * solc: ^0.5.1 -> 0.5.1 4 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.14.md: -------------------------------------------------------------------------------- 1 | With this release, Waffle introduces support human-readable abi as an output. 2 | 3 | Human readable ABI was introduced in ethers.js by @ricmoo in a [blog post](https://blog.ricmoo.com/human-readable-contract-abis-in-ethers-js-141902f4d917). 4 | 5 | To enable it, specify the following flag in Waffle config file: 6 | 7 | ```json 8 | { 9 | ... 10 | outputHumanReadableAbi: true 11 | } 12 | ``` 13 | 14 | You will now see the following in your output: 15 | ```json 16 | { 17 | ... 18 | "humanReadableAbi": [ 19 | "constructor(uint256 argOne)", 20 | "event Bar(bool argOne, uint256 indexed argTwo)", 21 | "event FooEvent()", 22 | "function noArgs() view returns(uint200)", 23 | "function oneArg(bool argOne)", 24 | "function threeArgs(string argOne, bool argTwo, uint256[] argThree) view returns(bool, uint256)", 25 | "function twoReturns(bool argOne) view returns(bool, uint256)" 26 | ] 27 | } 28 | ``` -------------------------------------------------------------------------------- /docs/release-notes/2.0.15.md: -------------------------------------------------------------------------------- 1 | * Upgrade solc to 0.5.10 2 | * deployContract accepts two formats now: 3 | ```ts 4 | interface StandardContractJSON { 5 | abi: any; 6 | evm: {bytecode: {object: any}}; 7 | } 8 | 9 | interface SimpleContractJSON { 10 | abi: any[]; 11 | bytecode: string; 12 | } 13 | ``` 14 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.16.md: -------------------------------------------------------------------------------- 1 | * Throw an informative exception when trying to deploy empty bytecode 2 | * Solcjs version can be specified bypassing the path in the configuration file, i.e.: 3 | ```ts 4 | { 5 | ... 6 | "solcVersion": "./node_modules/solc" 7 | } 8 | ``` 9 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.2.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | This release introduces typescript declaration files. This is required to enable 3 | TypeScript support when using the library. 4 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.3.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | This release introduces TypeScript declaration files for custom matchers and 3 | a rewrite of the compiler. 4 | 5 | ## Type declarations for custom matchers 6 | You can now enjoy full type safety when writing your tests with waffle. 7 | 8 | ## Compiler rewrite 9 | While no external facing api is changing the internals of the compiler have been 10 | rewritten to enable further developments. 11 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.4.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | Fixes version of web3js resolution 1.0.0-beta.37. Newer versions are unstable and break basic functionality. Fixes #69. -------------------------------------------------------------------------------- /docs/release-notes/2.0.5.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | This version introduces resolver-engine as a dependency. It is used for import standard import resolution. 3 | 4 | Functionality that it adds to the project: 5 | 6 | * [x] Filesystem, relative and absolute imports 7 | * [x] NPM and node_modules with support for monorepo pattern 8 | * [x] URI and URL support 9 | * [x] Github and branch support 10 | * [x] IPFS through a gateway 11 | * [x] Swarm through a gateway 12 | 13 | Additionally, backwards compatibility was added to support Waffle's original resolution methods 14 | 15 | 16 | ## About Resolver-Engine 17 | [Resolver-Engine](https://github.com/Crypto-Punkers/resolver-engine) project is an [Ethereum Foundation grantee](https://blog.ethereum.org/2018/08/17/ethereum-foundation-grants-update-wave-3/), with a goal to create tooling for standardised Solidity import resolution. 18 | 19 | In the past each and every framework has a different way of resolving imports, causing great anguish for the end-developers. With the Resolver-Engine, all projects that use it have a common set of supported functionality, sane defaults and maintenance of a dedicated team meaning that in the future Waffle will be able to support more imports just by upgrading the dependency. 20 | 21 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.6.md: -------------------------------------------------------------------------------- 1 | Bump ganache version to 2.4.0 -------------------------------------------------------------------------------- /docs/release-notes/2.0.7.md: -------------------------------------------------------------------------------- 1 | # Summary 2.0.7 2 | 3 | Add support for custom compiler options in waffle configuration file. Example below. 4 | 5 | ```js 6 | { 7 | "compilerOptions": { 8 | "evmVersion": "constantinople" 9 | }, 10 | "compiler": "native" 11 | } 12 | ``` 13 | 14 | For detailed list of options go to [solidity documentation](https://solidity.readthedocs.io/en/v0.5.1/using-the-compiler.html#using-the-compiler) (sections: ['Setting the EVM version to target'](https://solidity.readthedocs.io/en/v0.5.1/using-the-compiler.html#setting-the-evm-version-to-target), ['Target options'](https://solidity.readthedocs.io/en/v0.5.1/using-the-compiler.html#target-options) and ['Compiler Input and Output JSON Description'](https://solidity.readthedocs.io/en/v0.5.1/using-the-compiler.html#compiler-input-and-output-json-description)). 15 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.8.md: -------------------------------------------------------------------------------- 1 | This release contains minor features and bug fixes: 2 | * Update deployContract to work with Infura (by @sz-piotr) 3 | * Added support to Ganache revert reason in transaction responses (by @fredfortier) 4 | 5 | And `Readme.md` updates: 6 | * step-by-step how to run example and instructions (by @marekkirejczyk) 7 | * running test localy (by @AlexXiong97) 8 | 9 | -------------------------------------------------------------------------------- /docs/release-notes/2.0.9.md: -------------------------------------------------------------------------------- 1 | This release contains a minor feature. 2 | 3 | Extend configuration file to support async operations. -------------------------------------------------------------------------------- /docs/release-notes/2.1.0.md: -------------------------------------------------------------------------------- 1 | Features: 2 | * Ability to modify default provider gasLimit and gasPrice in createMockProvider(). It can be object with path to config file, e.g.: 3 | ```ts 4 | provider = createMockProvider({gasLimit: 0x6691b7, gasPrice: 0x77359400}); 5 | ``` 6 | 7 | or 8 | 9 | ```ts 10 | provider = createMockProvider('./waffle.json'); 11 | ``` 12 | 13 | waffle.json: 14 | ```ts 15 | { 16 | ... 17 | "ganacheOptions": { 18 | "gasLimit": "0x6691b7", 19 | "gasPrice": "0x77359400" 20 | } 21 | } 22 | ``` 23 | 24 | Bugfixes and maintance: 25 | * Fix ganache-core version to 2.6.1 (seems stable) 26 | * Update yarn.lock 27 | * Move @types/ganache-core to dependencies 28 | 29 | Note: 30 | * Form this versions we start using semantic versioning. -------------------------------------------------------------------------------- /docs/release-notes/2.1.1.md: -------------------------------------------------------------------------------- 1 | This release includes number of minor improvements and updates: 2 | * Fix targetPath not working for nested paths 3 | * Improved CLI 4 | * Improved documentation 5 | * Use eslint instead of tslint 6 | * Update typescript to 3.6.4 7 | * Update to Ganache-core 2.8.0 8 | -------------------------------------------------------------------------------- /docs/release-notes/2.1.2.md: -------------------------------------------------------------------------------- 1 | This release includes one bug fix: 2 | * Fix handling BigNumbers array as argument of the event log 3 | -------------------------------------------------------------------------------- /docs/release-notes/2.2.0.md: -------------------------------------------------------------------------------- 1 | This release is focused on configuration improvements. 2 | 3 | Changes: 4 | * Replace Travis CI with CircleCI 5 | * Make `ES2018` the compilation target as this is what Node 10 supports 6 | * Add two compilation outputs `CommonJS` and `ES Modules` 7 | * Move source files from `/lib` to `/src` 8 | -------------------------------------------------------------------------------- /docs/release-notes/2.3.0.md: -------------------------------------------------------------------------------- 1 | Changes: 2 | * Istanbul support 3 | * Migrate repository to a monorepo. Packages: 4 | - `waffle-cli` - direct successor to the previous repository root 5 | - `waffle-chai` - home of the chai matchers 6 | - `waffle-provider` - implementation of the `MockProvider` and fixtures 7 | - `waffle-compiler` - compilation of Solidity smart contracts 8 | * Add `MockProvider` class 9 | - it extends `providers.Web3Provider` 10 | - you create it using `new MockProvider(options?)` instead of `createMockProvider(options?)` 11 | - use `provider.getWallets()` instead of `getWallets(provider)`. This allows for a shorthand: `new MockProvider().getWallets()` 12 | - use `provider.createEmptyWallet()` to get a random Wallet without any ETH 13 | * Deprecate `createMockProvider` 14 | * Deprecate `getGanacheOptions` 15 | * Deprecate `getWallets` 16 | -------------------------------------------------------------------------------- /docs/release-notes/2.3.1.md: -------------------------------------------------------------------------------- 1 | Changes: 2 | * Fix ganache's "Incompatible EIP155" error 3 | -------------------------------------------------------------------------------- /docs/release-notes/2.3.2.md: -------------------------------------------------------------------------------- 1 | Changes: 2 | * Introduce `MockProviderLike` interface that enables third party providers to use the legacy `getWallets` api. 3 | -------------------------------------------------------------------------------- /docs/release-notes/2.4.0.md: -------------------------------------------------------------------------------- 1 | ## Features: 2 | 3 | * new cleaner, simple configuration file, detailed description available in the [documentation](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration-file). The configuration file format is backward compatible. 4 | 5 | 6 | ## Dependencies: 7 | 8 | * Update ethers version from ^4.0.0 to ^4.0.45 9 | 10 | ## Bug fixes: 11 | 12 | * Fixed `revertedWith('...')` to work corretly with string argument 13 | * Correct mismatched error reports `reverted` and `not.reverted` 14 | * `expect().to.emit.withArgs` - recognises when an event is emitted multiple times with different args, e.g. 15 | 16 | ```ts 17 | expect(...).to 18 | .emit(contractA, "SuccessCall").withArgs(1) 19 | .emit(contractB, "SuccessCall").withArgs(0) 20 | ``` 21 | 22 | -------------------------------------------------------------------------------- /docs/release-notes/2.4.1.md: -------------------------------------------------------------------------------- 1 | ## Changes: 2 | * Add support for tuple types in the human readable abi 3 | * Increase max output buffer size during native and docker compilation 4 | * Fix big number matchers (e.g `to.be.gt`) 5 | * Add more big number matchers (`above`, `below`, `least`, `most`) 6 | -------------------------------------------------------------------------------- /docs/release-notes/2.5.0.md: -------------------------------------------------------------------------------- 1 | ## Changes: 2 | * Add calledOnContract matchers 3 | 4 | 5 | * Add dockerized Vyper compilation (experimental), configurable from waffle.json file: 6 | ```json 7 | "compilerType": "dockerized-vyper", 8 | "compilerVersion": "0.1.0" 9 | ``` 10 | 11 | * Add flattener, launch from command line: 12 | ```sh 13 | npx waffle flatten 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/release-notes/3.0.0-beta.1.md: -------------------------------------------------------------------------------- 1 | This prerelease migrates to ethers v5 -------------------------------------------------------------------------------- /docs/release-notes/3.0.0-beta.2.md: -------------------------------------------------------------------------------- 1 | Introduce better ens support -------------------------------------------------------------------------------- /docs/release-notes/3.0.0-beta.3.md: -------------------------------------------------------------------------------- 1 | * Add more examples 2 | * Improve Waffle documentation 3 | -------------------------------------------------------------------------------- /docs/release-notes/3.0.0.md: -------------------------------------------------------------------------------- 1 | ## Changes: 2 | 3 | 4 | * Introduced better ens support. 5 | 6 | * Updated EthersJS version to ^5.0.0. 7 | 8 | * Removed deprecated APIs from the provider. 9 | 10 | * Swapped arguments for Fixture. 11 | 12 | ```ts 13 | function createFixtureLoader(wallets: Wallet[], provider?: MockProvider); 14 | ``` 15 | 16 | * Added automatic recognising waffle.json config without cli argument. 17 | 18 | ```json 19 | { 20 | "scripts": { 21 | "build": "waffle" 22 | } 23 | } 24 | ``` 25 | 26 | * Introduced MockProviderOptions 27 | 28 | ```ts 29 | const provider = new MockProvider({ 30 | ganacheOptions: { 31 | accounts: [{balance: '100', secretKey: privateKey}] 32 | } 33 | }); 34 | ``` 35 | 36 | * Dropped support for contract interface 37 | 38 | * Improved documentation 39 | 40 | * Added migration guides for different Waffle versions 41 | -------------------------------------------------------------------------------- /docs/release-notes/3.0.1.md: -------------------------------------------------------------------------------- 1 | This release fixes following bugs: 2 | * Fix revertedWith matcher false positive behaviour 3 | * Make emit matcher error messages follow chai convention 4 | * Load config from provided path by default -------------------------------------------------------------------------------- /docs/release-notes/3.0.2.md: -------------------------------------------------------------------------------- 1 | This release replace uses of Wallet with Signer in changeBalance(s) matchers and for fixtures. 2 | -------------------------------------------------------------------------------- /docs/release-notes/3.0.3: -------------------------------------------------------------------------------- 1 | * Fix source maps 2 | * Mocks can now call and staticcall through to contracts 3 | * Mock can now revert with reason in doppelganger contract (#349) 4 | -------------------------------------------------------------------------------- /docs/release-notes/3.1.0.md: -------------------------------------------------------------------------------- 1 | * Introduce experimental support for Jest 2 | * Revert breaking change from Wallet to Signer in Fixture 3 | * Export Fixture type 4 | -------------------------------------------------------------------------------- /docs/release-notes/3.1.1.md: -------------------------------------------------------------------------------- 1 | * Remove multiple SPDX licence during flattening 2 | * Allow transaction receipt in balance matchers 3 | * Skip solc download if version is already present 4 | * Add revertsWithReason to mock contract documentation 5 | * Fix broken markdown in waffle-cli readme 6 | -------------------------------------------------------------------------------- /docs/release-notes/3.1.2.md: -------------------------------------------------------------------------------- 1 | * Add changeTokenBalance matcher 2 | * Fix staticcall for calls with multiple parameters -------------------------------------------------------------------------------- /docs/release-notes/3.2.0.md: -------------------------------------------------------------------------------- 1 | * Caching solcjs binaries which allows faster test execution on slow internet and offline 2 | * Remove deployContract's default `gasPrice` and `gasLimit` (use etheres defaults instead) 3 | * New matchers `changeEtherBalance` and `changeEtherBalances` to replaces `changeBalance` and add support for transaction fees by deafult. -------------------------------------------------------------------------------- /docs/release-notes/3.2.1.md: -------------------------------------------------------------------------------- 1 | * Make solcjs compilation work with versions >=0.7.2 2 | -------------------------------------------------------------------------------- /docs/release-notes/3.2.2.md: -------------------------------------------------------------------------------- 1 | * Allow asserting events on previously executed transactions (#424) 2 | * Make BN matchers compatible with chai's lengthOf (#423) 3 | * expect().to.emit().withArgs() - add assertion for indexed dynamic size parameters (#413) 4 | * Add hexEqual matcher (#415) 5 | * Update types for matchers to explicitly return promises (#403) 6 | * Update dev dependencies, replace node 11 with 14 7 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx==3.0.3 2 | pygments-lexer-solidity==0.5.1 3 | sphinx-rtd-theme==0.4.3 4 | sphinx-tabs==1.1.13 5 | jinja2==3.0.3 6 | -------------------------------------------------------------------------------- /docs/source/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrueFiEng/Waffle/238c11ccf9bcaf4b83c73eca16d25243c53f2210/docs/source/_static/.gitkeep -------------------------------------------------------------------------------- /docs/source/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrueFiEng/Waffle/238c11ccf9bcaf4b83c73eca16d25243c53f2210/docs/source/_static/favicon.ico -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Waffle Documentation 2 | ==================== 3 | 4 | .. image:: logo.png 5 | 6 | Waffle is a library for writing and testing smart contracts. 7 | 8 | Sweeter, simpler and faster than Truffle. 9 | 10 | Works with ethers-js. 11 | 12 | Philosophy: 13 | ----------- 14 | - **Simpler**: Minimalistic, few dependencies. 15 | - **Sweeter**: Nice syntax, easy to extend. 16 | - **Faster**: Focus on the speed of tests execution. 17 | 18 | Features: 19 | --------- 20 | - Sweet set of chai matchers, 21 | - Easy contract importing from npm modules, 22 | - Fast compilation with native and dockerized solc, 23 | - Typescript compatible, 24 | - Fixtures that help write fast and maintainable test suites, 25 | - Well documented. 26 | 27 | Versions and ethers compatibility 28 | --------------------------------- 29 | - Use version :code:`0.2.3` with ethers 3 and solidity 4, 30 | - Use version :code:`1.2.0` with ethers 4 and solidity 4, 31 | - Use version :code:`2.*.*` with ethers 4, solidity 4, 5 and ability to use native or dockerized solc. 32 | - Use version :code:`3.*.*` with ethers 5, solidity 4, 5, 6 and ability to use native, dockerized solc or dockerized vyper. 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | :caption: Contents: 37 | 38 | getting-started.rst 39 | compilation.rst 40 | basic-testing.rst 41 | matchers.rst 42 | fixtures.rst 43 | mock-contract.rst 44 | ens.rst 45 | configuration.rst 46 | migration-guides.rst 47 | -------------------------------------------------------------------------------- /docs/source/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrueFiEng/Waffle/238c11ccf9bcaf4b83c73eca16d25243c53f2210/docs/source/logo.png -------------------------------------------------------------------------------- /examples/.eslintrc.example.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.json') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | overrides: [ 6 | { 7 | files: [ 8 | "test/**/*.ts" 9 | ], 10 | rules: { 11 | "import/no-extraneous-dependencies": "off" 12 | } 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /examples/basic/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-basic", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "export NODE_ENV=test && mocha", 8 | "build": "waffle waffle.json", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "@types/chai": "^4.2.3", 14 | "@types/mocha": "^5.2.7", 15 | "chai": "^4.2.0", 16 | "eslint": "^7.14.0", 17 | "ethereum-waffle": "workspace:*", 18 | "ethers": "5.6.2", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2", 22 | "@openzeppelin/contracts": "^3.0.0" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /examples/basic/src/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 | 5 | // Example class - a mock class using delivering from ERC20 6 | contract BasicToken is ERC20 { 7 | constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { 8 | _mint(msg.sender, initialBalance); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/basic/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/basic/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.6.2", 4 | "sourceDirectory": "./src", 5 | "outputDirectory": "./build" 6 | } 7 | -------------------------------------------------------------------------------- /examples/called-on-contract/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/called-on-contract/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-called-on-contract", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "export NODE_ENV=test && mocha", 8 | "build": "waffle waffle.json", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "@types/chai": "^4.2.3", 14 | "@types/mocha": "^5.2.7", 15 | "chai": "^4.2.0", 16 | "eslint": "^7.14.0", 17 | "ethereum-waffle": "workspace:*", 18 | "ethers": "5.6.2", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2", 22 | "@openzeppelin/contracts": "^3.4.2" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /examples/called-on-contract/src/AmIRichAlready.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.2; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 | 5 | contract BasicToken is ERC20 { 6 | constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { 7 | _mint(msg.sender, initialBalance); 8 | } 9 | } 10 | 11 | contract AmIRichAlready { 12 | BasicToken private tokenContract; 13 | uint private constant RICHNESS = 1000000 * 10 ** 18; 14 | constructor (BasicToken _tokenContract) public { 15 | tokenContract = _tokenContract; 16 | } 17 | 18 | function check() public view returns (bool) { 19 | uint balance = tokenContract.balanceOf(msg.sender); 20 | return balance > RICHNESS; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/called-on-contract/test/AmIRichAlready.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, use} from 'chai'; 2 | import {Contract, utils} from 'ethers'; 3 | import {deployContract, MockProvider, solidity} from 'ethereum-waffle'; 4 | 5 | import BasicToken from '../build/BasicToken.json'; 6 | import AmIRichAlready from '../build/AmIRichAlready.json'; 7 | 8 | use(solidity); 9 | 10 | describe('Am I Rich Already', () => { 11 | let ERC20: Contract; 12 | let contract: Contract; 13 | const [wallet] = new MockProvider().getWallets(); 14 | 15 | it('returns false if the wallet has less then 1000000 coins', async () => { 16 | ERC20 = await deployContract(wallet, BasicToken, [utils.parseEther('999999')]); 17 | contract = await deployContract(wallet, AmIRichAlready, [ERC20.address]); 18 | expect(await contract.check()).to.be.equal(false); 19 | expect('balanceOf').to.be.calledOnContract(ERC20); 20 | }); 21 | 22 | it('returns true if the wallet has more than 1000000 coins', async () => { 23 | ERC20 = await deployContract(wallet, BasicToken, [utils.parseEther('1000001')]); 24 | contract = await deployContract(wallet, AmIRichAlready, [ERC20.address]); 25 | expect(await contract.check()).to.equal(true); 26 | expect('balanceOf').to.be.calledOnContractWith(ERC20, [wallet.address]); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /examples/called-on-contract/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/called-on-contract/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/called-on-contract/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.6.2", 4 | "sourceDirectory": "./src", 5 | "outputDirectory": "./build" 6 | } 7 | -------------------------------------------------------------------------------- /examples/change-balance/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/change-balance/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-change-balance", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "true", 8 | "test": "export NODE_ENV=test && mocha", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "@types/chai": "^4.2.3", 14 | "@types/mocha": "^5.2.7", 15 | "chai": "^4.2.0", 16 | "eslint": "^7.14.0", 17 | "ethereum-waffle": "workspace:*", 18 | "ethers": "5.6.2", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2" 22 | }, 23 | "private": true 24 | } 25 | -------------------------------------------------------------------------------- /examples/change-balance/test/ChangeBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, use} from 'chai'; 2 | import {MockProvider, solidity} from 'ethereum-waffle'; 3 | 4 | use(solidity); 5 | 6 | describe('BasicToken', () => { 7 | const [walletFrom, walletTo] = new MockProvider().getWallets(); 8 | 9 | it('Change balance of receiver wallet', async () => { 10 | await expect(() => 11 | walletFrom.sendTransaction({ 12 | to: walletTo.address, 13 | gasPrice: 0, 14 | value: 200 15 | }) 16 | ).to.changeBalance(walletTo, 200); 17 | }); 18 | 19 | it('Change balance of receiver and sander wallets', async () => { 20 | await expect(() => 21 | walletFrom.sendTransaction({ 22 | to: walletTo.address, 23 | gasPrice: 0, 24 | value: 200 25 | }) 26 | ).to.changeBalances([walletFrom, walletTo], [-200, 200]); 27 | }); 28 | 29 | it('Change balance of receiver and sander wallets including the gas price', async () => { 30 | await expect(() => 31 | walletFrom.sendTransaction({ 32 | to: walletTo.address, 33 | gasPrice: 1, 34 | value: 200 35 | }) 36 | ).to.changeBalances([walletFrom, walletTo], [-21200, 200]); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /examples/change-balance/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/change-balance/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-dynamic-mocking-and-testing-calls", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "export NODE_ENV=test && mocha", 8 | "build": "waffle", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "@types/chai": "^4.2.3", 14 | "@types/mocha": "^5.2.7", 15 | "chai": "^4.2.0", 16 | "eslint": "^7.14.0", 17 | "ethereum-waffle": "workspace:*", 18 | "ethers": "5.6.2", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2" 22 | }, 23 | "private": true 24 | } 25 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/src/AmIRichAlready.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.2; 2 | 3 | interface IERC20 { 4 | function balanceOf(address account) external view returns (uint256); 5 | } 6 | 7 | contract AmIRichAlready { 8 | IERC20 private tokenContract; 9 | uint public richness = 1000000 * 10 ** 18; 10 | 11 | constructor (IERC20 _tokenContract) public { 12 | tokenContract = _tokenContract; 13 | } 14 | 15 | function check() public view returns (bool) { 16 | uint balance = tokenContract.balanceOf(msg.sender); 17 | return balance > richness; 18 | } 19 | 20 | // IS THIS NEEDED??? 21 | function setRichness(uint256 _richness) public { 22 | richness = _richness; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/dynamic-mocking-and-testing-calls/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.6.2", 4 | "sourceDirectory": "./src", 5 | "outputDirectory": "./build" 6 | } 7 | -------------------------------------------------------------------------------- /examples/ens/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/ens/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-ens", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "true", 8 | "test": "export NODE_ENV=test && mocha", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "ethers": "5.6.2", 14 | "@types/chai": "^4.2.3", 15 | "@types/mocha": "^5.2.7", 16 | "chai": "^4.2.0", 17 | "eslint": "^7.14.0", 18 | "@ethereum-waffle/provider": "workspace:*", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2", 22 | "chai-as-promised": "^7.1.1" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /examples/ens/test/ENS.test.ts: -------------------------------------------------------------------------------- 1 | import chai, {expect} from 'chai'; 2 | import {utils} from 'ethers'; 3 | import {MockProvider} from '@ethereum-waffle/provider'; 4 | import chaiAsPromised from 'chai-as-promised'; 5 | 6 | chai.use(chaiAsPromised); 7 | 8 | const {namehash} = utils; 9 | 10 | describe('Deploy Ens', async () => { 11 | const provider = new MockProvider(); 12 | const [wallet] = provider.getWallets(); 13 | 14 | before(async () => { 15 | await provider.setupENS(); 16 | }); 17 | 18 | it('Create domain recursive', async () => { 19 | const node = namehash('ethworks.tld'); 20 | await provider.ens.createSubDomain('ethworks.tld', {recursive: true}); 21 | expect(await provider.ens.ens.owner(node)).to.eq(provider.ens.registrars['ethworks.tld'].address); 22 | expect(await provider.ens.ens.resolver(node)).to.eq(provider.ens.resolver.address); 23 | }); 24 | 25 | it('Set address', async () => { 26 | await provider.ens.setAddress('vlad.ethworks.tld', wallet.address); 27 | expect(await provider.resolveName('vlad.ethworks.tld')).to.eq(wallet.address); 28 | }); 29 | 30 | it('Set address with reverse ', async () => { 31 | await provider.ens.setAddressWithReverse('vlad.ethworks.test', wallet, {recursive: true}); 32 | expect(await provider.lookupAddress(wallet.address)).to.eq('vlad.ethworks.test'); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/ens/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.ts 5 | -------------------------------------------------------------------------------- /examples/ens/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-provider" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/mock-contracts/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/mock-contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-mock-contract", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "export NODE_ENV=test && mocha", 8 | "build": "waffle waffle.json", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "ethers": "5.6.2", 14 | "@types/chai": "^4.2.3", 15 | "@types/mocha": "^5.2.7", 16 | "chai": "^4.2.0", 17 | "eslint": "^7.14.0", 18 | "ethereum-waffle": "workspace:*", 19 | "mocha": "^7.1.2", 20 | "ts-node": "^8.9.1", 21 | "typescript": "^4.6.2" 22 | }, 23 | "private": true 24 | } 25 | -------------------------------------------------------------------------------- /examples/mock-contracts/src/AmIRichAlready.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.15; 2 | 3 | interface IERC20 { 4 | function balanceOf(address account) external view returns (uint256); 5 | } 6 | 7 | contract AmIRichAlready { 8 | IERC20 private tokenContract; 9 | uint private constant RICHNESS = 1000000 * 10 ** 18; 10 | constructor (IERC20 _tokenContract) public { 11 | tokenContract = _tokenContract; 12 | } 13 | 14 | function check() public view returns (bool) { 15 | uint balance = tokenContract.balanceOf(msg.sender); 16 | return balance > RICHNESS; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mock-contracts/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/mock-contracts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/mock-contracts/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.5.15", 4 | "sourceDirectory": "./src", 5 | "outputDirectory": "./build" 6 | } 7 | -------------------------------------------------------------------------------- /examples/typechain-example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | const baseConfig = require('../.eslintrc.example.js') 2 | 3 | module.exports = { 4 | ...baseConfig, 5 | } 6 | -------------------------------------------------------------------------------- /examples/typechain-example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # example-typechain 2 | 3 | ## 1.0.1 4 | 5 | ### Patch Changes 6 | 7 | - 00e9f1b: 🪵 Upgrade solc 8 | -------------------------------------------------------------------------------- /examples/typechain-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-typechain", 3 | "version": "1.0.1", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "export NODE_ENV=test && mocha", 8 | "build": "waffle waffle.json", 9 | "lint": "eslint '{src,test}/**/*.ts'", 10 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 11 | }, 12 | "devDependencies": { 13 | "@openzeppelin/contracts": "^3.0.0", 14 | "@types/chai": "^4.2.3", 15 | "@types/mocha": "^5.2.7", 16 | "chai": "^4.2.0", 17 | "eslint": "^7.14.0", 18 | "ethereum-waffle": "workspace:*", 19 | "ethers": "5.6.2", 20 | "mocha": "^7.1.2", 21 | "solc": "0.8.15", 22 | "ts-node": "^8.9.1", 23 | "typechain": "^8.0.0", 24 | "typescript": "^4.6.2" 25 | }, 26 | "private": true 27 | } 28 | -------------------------------------------------------------------------------- /examples/typechain-example/src/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.0; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 | 5 | // Example class - a mock class using delivering from ERC20 6 | contract BasicToken is ERC20 { 7 | constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { 8 | _mint(msg.sender, initialBalance); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/typechain-example/test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register/transpile-only 2 | --timeout 50000 3 | --no-warnings 4 | test/**/*.test.{js,ts} 5 | -------------------------------------------------------------------------------- /examples/typechain-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "references": [ 4 | { 5 | "path": "../../waffle-cli" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/typechain-example/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.6.2", 4 | "sourceDirectory": "./src", 5 | "outputDirectory": "./build", 6 | "typechainEnabled": true, 7 | "typechainOutputDir": "../typechain" 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "waffle-monorepo", 3 | "author": "Ethworks", 4 | "homepage": "https://getwaffle.io/", 5 | "private": true, 6 | "engines": { 7 | "node": ">=10.0" 8 | }, 9 | "scripts": { 10 | "lint": "pnpm run -r lint", 11 | "build": "pnpm run -r build", 12 | "test": "pnpm run -r test", 13 | "version": "pnpm changeset version", 14 | "release": "pnpm run build && pnpm changeset publish" 15 | }, 16 | "devDependencies": { 17 | "@types/chai": "^4.2.14", 18 | "@types/chai-as-promised": "^7.1.3", 19 | "@types/chai-string": "^1.4.2", 20 | "@types/mocha": "^8.0.4", 21 | "@types/rimraf": "^3.0.0", 22 | "@types/sinon": "^9.0.9", 23 | "@types/sinon-chai": "^3.2.5", 24 | "@typescript-eslint/eslint-plugin": "^5.15.0", 25 | "@typescript-eslint/parser": "^5.15.0", 26 | "chai": "^4.2.0", 27 | "chai-as-promised": "^7.1.1", 28 | "chai-string": "^1.5.0", 29 | "eslint-plugin-import": "^2.22.1", 30 | "eslint-plugin-no-only-tests": "^2.6.0", 31 | "sinon": "^9.2.1", 32 | "sinon-chai": "^3.5.0" 33 | }, 34 | "dependencies": { 35 | "@changesets/cli": "^2.22.0" 36 | }, 37 | "packageManager": "pnpm@7.1.9", 38 | "resolutions": { 39 | "underscore": ">=1.12.1", 40 | "lodash": ">=4.17.21", 41 | "mixme": ">=0.5.1" 42 | }, 43 | "version": "0.0.0" 44 | } 45 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - './waffle-*' 3 | - './examples/*' 4 | -------------------------------------------------------------------------------- /scripts/dev-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | DEV=$(jq -r ".version" package.json | awk -F "-" '{print $1}')-dev.$(git rev-parse --short HEAD) 5 | cat <<< "$(jq --arg DEV "$DEV" ".version = \"$DEV\"" package.json)" > package.json 6 | cat <<< "$(jq ".publishConfig.tag = \"dev\"" package.json)" > package.json 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "esModuleInterop": true, 5 | "lib": [ 6 | "ES2018" 7 | ], 8 | "module": "CommonJS", 9 | "moduleResolution": "node", 10 | "outDir": "dist", 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "strict": true, 14 | "target": "ES2018", 15 | "composite": true, 16 | "sourceMap": true, 17 | "declarationMap": true, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /waffle-chai/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-chai/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}', 6 | file: 'test/test-setup.ts' 7 | } 8 | -------------------------------------------------------------------------------- /waffle-chai/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | .eslintrc.js 4 | tsconfig.build.json 5 | tsconfig.json 6 | -------------------------------------------------------------------------------- /waffle-chai/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-chai/README.md: -------------------------------------------------------------------------------- 1 | ![CI](https://github.com/EthWorks/Waffle/workflows/CI/badge.svg) 2 | [![](https://img.shields.io/npm/v/@ethereum-waffle/chai.svg)](https://www.npmjs.com/package/@ethereum-waffle/chai) 3 | 4 | ![Ethereum Waffle](https://raw.githubusercontent.com/EthWorks/Waffle/master/docs/source/logo.png) 5 | 6 | # @ethereum-waffle/chai 7 | 8 | A sweet set of chai matchers for your blockchain testing needs. 9 | 10 | ## Installation 11 | 12 | In the current version of waffle (v2.x.x) you will install this package as a dependency of the main waffle package - `ethereum-waffle`. 13 | 14 | ``` 15 | yarn add --dev ethereum-waffle 16 | npm install --save-dev ethereum-waffle 17 | ``` 18 | 19 | If you want to use this package directly please install it via: 20 | ``` 21 | yarn add --dev @ethereum-waffle/chai 22 | npm install --save-dev @ethereum-waffle/chai 23 | ``` 24 | 25 | ## Usage 26 | ```ts 27 | import { expect, use } from "chai"; 28 | import { waffleChai } from "@ethereum-waffle/chai"; 29 | import { bigNumberify } from "ethers/utils"; 30 | 31 | use(chaiAsPromised); 32 | 33 | expect(bigNumberify("6")).to.be.gt(0); 34 | ``` 35 | 36 | ## Feature overview 37 | 38 | **NOTE**: You do not need to use this package directly. You can install it through the main package (`ethereum-waffle`) and use it instead. 39 | 40 | Read more [in the documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). 41 | -------------------------------------------------------------------------------- /waffle-chai/src/log.ts: -------------------------------------------------------------------------------- 1 | import debug from 'debug'; 2 | 3 | const log = debug('waffle:waffle-chai'); 4 | 5 | export {log}; 6 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/README.md: -------------------------------------------------------------------------------- 1 | Assert parameters 2 | 3 | - `expression` - expression to test for truthiness 4 | - `errorMessage` - text to display if expression is false 5 | - `negatedErrorMessage` - text to display if expression is true, when combined with `.not` 6 | - `expected` (optional) - what was expected 7 | - `actual` (optional) - what was provided 8 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/calledOnContract/calledOnContract.ts: -------------------------------------------------------------------------------- 1 | import {validateContract, validateFnName, validateMockProvider} from './calledOnContractValidators'; 2 | import {assertFunctionCalled} from './assertions'; 3 | 4 | export function supportCalledOnContract(Assertion: Chai.AssertionStatic) { 5 | Assertion.addMethod('calledOnContract', function (contract: any) { 6 | const fnName = this._obj; 7 | 8 | validateContract(contract); 9 | validateMockProvider(contract.provider); 10 | if (fnName !== undefined) { 11 | validateFnName(fnName, contract); 12 | } 13 | 14 | assertFunctionCalled(this, contract, fnName); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/calledOnContract/calledOnContractValidators.ts: -------------------------------------------------------------------------------- 1 | import {Contract} from 'ethers'; 2 | import {MockProvider} from '@ethereum-waffle/provider'; 3 | import {ProviderWithHistoryExpected} from './error'; 4 | import {ensure} from './utils'; 5 | 6 | export function validateContract(contract: any): asserts contract is Contract { 7 | const possiblyContract = contract as Contract; 8 | ensure( 9 | !!possiblyContract.address && !!possiblyContract.functions && !!possiblyContract.interface, TypeError, 10 | 'argument must be a contract' 11 | ); 12 | } 13 | 14 | export function validateMockProvider(provider: any): asserts provider is MockProvider { 15 | ensure( 16 | (!!provider.callHistory && provider.callHistory instanceof Array), ProviderWithHistoryExpected 17 | ); 18 | } 19 | 20 | export function validateFnName(fnName: any, contract: Contract): asserts fnName is string { 21 | ensure( 22 | typeof fnName === 'string', TypeError, 23 | 'function name must be a string' 24 | ); 25 | function isFunction(name: string) { 26 | try { 27 | return !!contract.interface.getFunction(name); 28 | } catch (e) { 29 | return false; 30 | } 31 | } 32 | ensure( 33 | isFunction(fnName), TypeError, 34 | 'function must exist in provided contract' 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/calledOnContract/calledOnContractWith.ts: -------------------------------------------------------------------------------- 1 | import {validateContract, validateFnName, validateMockProvider} from './calledOnContractValidators'; 2 | import {assertCalledWithParams} from './assertions'; 3 | 4 | export function supportCalledOnContractWith(Assertion: Chai.AssertionStatic) { 5 | Assertion.addMethod('calledOnContractWith', function (this: any, contract: any, parameters: any[]) { 6 | const fnName = this._obj; 7 | const negated = this.__flags.negate; 8 | 9 | validateContract(contract); 10 | validateMockProvider(contract.provider); 11 | validateFnName(fnName, contract); 12 | 13 | assertCalledWithParams(this, contract, fnName, parameters, negated); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/calledOnContract/error.ts: -------------------------------------------------------------------------------- 1 | export class ProviderWithHistoryExpected extends Error { 2 | constructor() { 3 | super('calledOnContract matcher requires provider that support call history'); 4 | } 5 | } 6 | 7 | export class EncodingError extends Error { 8 | error: Error | undefined; 9 | } 10 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/calledOnContract/utils.ts: -------------------------------------------------------------------------------- 1 | interface ErrorConstructor { 2 | new (...args: T): Error; 3 | } 4 | 5 | export function ensure(condition: boolean, ErrorToThrow: ErrorConstructor, ...errorArgs: T): 6 | asserts condition { 7 | if (!condition) { 8 | throw new ErrorToThrow(...errorArgs); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/hexEqual.ts: -------------------------------------------------------------------------------- 1 | export function supportHexEqual(Assertion: Chai.AssertionStatic) { 2 | Assertion.addMethod('hexEqual', function (this: any, other: string) { 3 | const subject = this._obj; 4 | const isNegated = this.__flags.negate === true; 5 | const isHex = (a: string) => /^0x[0-9a-fA-F]*$/.test(a); 6 | for (const element of [subject, other]) { 7 | if (!isHex(element)) { 8 | this.assert( 9 | isNegated, 10 | `Expected "${subject}" to be a hex string equal to "${other}", but "${element}" is not a valid hex string`, 11 | `Expected "${subject}" not to be a hex string equal to "${other}", but "${element}" is not a valid hex string` 12 | ); 13 | } 14 | } 15 | const extractNumeric = (hex: string) => hex.replace(/^0x0*/, ''); 16 | this.assert( 17 | extractNumeric(subject.toLowerCase()) === extractNumeric(other.toLowerCase()), 18 | `Expected "${subject}" to be a hex string equal equal to "${other}"`, 19 | `Expected "${subject}" not to a hex string equal be equal to "${other}", but it was`, 20 | `Hex string representing the same number as ${other}`, 21 | subject 22 | ); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/misc/account.ts: -------------------------------------------------------------------------------- 1 | import {Contract, Signer} from 'ethers'; 2 | 3 | export type Account = Signer | Contract; 4 | 5 | export async function getAddressOf(account: Account) { 6 | return (account as Contract).address ?? account.getAddress(); 7 | } 8 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/misc/balance.ts: -------------------------------------------------------------------------------- 1 | import {BigNumberish} from 'ethers'; 2 | import {ensure} from '../calledOnContract/utils'; 3 | import {Account, getAddressOf} from './account'; 4 | 5 | export interface BalanceChangeOptions { 6 | includeFee?: boolean; 7 | errorMargin?: BigNumberish; 8 | } 9 | 10 | export function getAddresses(accounts: Account[]) { 11 | return Promise.all(accounts.map((account) => getAddressOf(account))); 12 | } 13 | 14 | export async function getBalances(accounts: Account[], blockNumber?: number) { 15 | return Promise.all( 16 | accounts.map((account) => { 17 | ensure(account.provider !== undefined, TypeError, 'Provider not found'); 18 | if (blockNumber !== undefined) { 19 | return account.provider.getBalance(getAddressOf(account), blockNumber); 20 | } else { 21 | return account.provider.getBalance(getAddressOf(account)); 22 | } 23 | }) 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/misc/struct.ts: -------------------------------------------------------------------------------- 1 | export const isStruct = (arr: any[]) => { 2 | if (!Array.isArray(arr)) return false; 3 | const keys = Object.keys(arr); 4 | const hasAlphaNumericKeys = keys.some((key) => key.match(/^[a-zA-Z0-9]*[a-zA-Z]+[a-zA-Z0-9]*$/)); 5 | const hasNumericKeys = keys.some((key) => key.match(/^\d+$/)); 6 | return hasAlphaNumericKeys && hasNumericKeys; 7 | }; 8 | 9 | export const convertStructToPlainObject = (struct: any[]): any => { 10 | const keys = Object.keys(struct).filter((key: any) => isNaN(key)); 11 | return keys.reduce( 12 | (acc: any, key: any) => ({ 13 | ...acc, 14 | [key]: isStruct(struct[key]) 15 | ? convertStructToPlainObject(struct[key]) 16 | : struct[key] 17 | }), 18 | {} 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/misc/transaction.ts: -------------------------------------------------------------------------------- 1 | import type {Transaction, providers} from 'ethers'; 2 | 3 | export type MaybePendingTransaction = Promise | Transaction | string; 4 | 5 | export async function waitForPendingTransaction(tx: MaybePendingTransaction, provider: providers.Provider) { 6 | let hash: string | undefined; 7 | if (tx instanceof Promise) { 8 | ({hash} = await tx); 9 | } else if (typeof tx === 'string') { 10 | hash = tx; 11 | } else { 12 | ({hash} = tx); 13 | } 14 | if (!hash) { 15 | throw new Error(`${tx} is not a valid transaction`); 16 | } 17 | return provider.waitForTransaction(hash); 18 | } 19 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/properAddress.ts: -------------------------------------------------------------------------------- 1 | export function supportProperAddress(Assertion: Chai.AssertionStatic) { 2 | Assertion.addProperty('properAddress', function (this: any) { 3 | const subject = this._obj; 4 | this.assert( 5 | /^0x[0-9-a-fA-F]{40}$/.test(subject), 6 | `Expected "${subject}" to be a proper address`, 7 | `Expected "${subject}" not to be a proper address`, 8 | 'proper address (eg.: 0x1234567890123456789012345678901234567890)', 9 | subject 10 | ); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/properHex.ts: -------------------------------------------------------------------------------- 1 | export function supportProperHex(Assertion: Chai.AssertionStatic) { 2 | Assertion.addMethod('properHex', function (this: any, length: number) { 3 | const subject = this._obj; 4 | const regexp = new RegExp(`^0x[0-9-a-fA-F]{${length}}$`); 5 | this.assert(regexp.test(subject), 6 | `Expected "${subject}" to be a proper hex of length ${length}`, 7 | `Expected "${subject}" not to be a proper hex of length ${length}, but it was`, 8 | 'proper address (eg.: 0x1234567890123456789012345678901234567890)', 9 | subject); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/properPrivateKey.ts: -------------------------------------------------------------------------------- 1 | export function supportProperPrivateKey(Assertion: Chai.AssertionStatic) { 2 | Assertion.addProperty('properPrivateKey', function (this: any) { 3 | const subject = this._obj; 4 | this.assert( 5 | /^0x[0-9-a-fA-F]{64}$/.test(subject), 6 | `Expected "${subject}" to be a proper private key`, 7 | `Expected "${subject}" not to be a proper private key`, 8 | 'proper address (eg.: 0x1234567890123456789012345678901234567890)', 9 | subject 10 | ); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /waffle-chai/src/matchers/reverted.ts: -------------------------------------------------------------------------------- 1 | import {callPromise} from '../call-promise'; 2 | 3 | export function supportReverted(Assertion: Chai.AssertionStatic) { 4 | Assertion.addProperty('reverted', function (this: any) { 5 | callPromise(this); 6 | const onError = (error: any) => { 7 | const message = (error instanceof Object && 'message' in error) ? error.message : JSON.stringify(error); 8 | const isReverted = message.search('revert') >= 0; 9 | const isThrown = message.search('invalid opcode') >= 0; 10 | const isError = message.search('code=') >= 0; 11 | this.assert( 12 | isReverted || isThrown || isError, 13 | `Expected transaction to be reverted, but other exception was thrown: ${error}`, 14 | `Expected transaction NOT to be reverted, but it was reverted with "${message}"`, 15 | 'Transaction reverted.', 16 | error 17 | ); 18 | return error; 19 | }; 20 | 21 | const assertNotReverted = () => this.assert( 22 | false, 23 | 'Expected transaction to be reverted', 24 | 'Expected transaction NOT to be reverted', 25 | 'Transaction reverted.', 26 | 'Transaction NOT reverted.' 27 | ); 28 | 29 | this.callPromise = this.callPromise.then(assertNotReverted, onError); 30 | this.then = this.callPromise.then.bind(this.callPromise); 31 | this.catch = this.callPromise.catch.bind(this.callPromise); 32 | return this; 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /waffle-chai/test/index.ts: -------------------------------------------------------------------------------- 1 | export {calledOnContractTest} from './matchers/calledOnContract/calledOnContractTest'; 2 | export {calledOnContractValidatorsTest} from './matchers/calledOnContract/calledOnContractValidatorsTest'; 3 | export {calledOnContractWithTest} from './matchers/calledOnContract/calledOnContractWithTest'; 4 | export {chainingMatchersTest} from './matchers/chainingTest'; 5 | export {changeEtherBalanceTest} from './matchers/changeEtherBalanceTest'; 6 | export {changeEtherBalancesTest} from './matchers/changeEtherBalancesTest'; 7 | export {changeTokenBalanceTest} from './matchers/changeTokenBalanceTest'; 8 | export {changeTokenBalancesTest} from './matchers/changeTokenBalancesTest'; 9 | export {eventsTest} from './matchers/eventsTest'; 10 | export {revertedTest} from './matchers/revertedTest'; 11 | export {revertedWithTest} from './matchers/revertedWithTest'; 12 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/MockProviderCases.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This import only works when inside the monorepo. 3 | * It is OK because we do not publish the `test` directory on NPM. 4 | */ 5 | export {describeMockProviderCases} from '@ethereum-waffle/provider/test/MockProviderCases'; 6 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/calledOnContract/calledOnContract.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from '../MockProviderCases'; 2 | import {calledOnContractTest} from './calledOnContractTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: calledOnContract', (provider) => { 5 | calledOnContractTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/calledOnContract/calledOnContractValidators.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from '../MockProviderCases'; 2 | import {calledOnContractValidatorsTest} from './calledOnContractValidatorsTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: ethCalledValidators', (provider) => { 5 | calledOnContractValidatorsTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/calledOnContract/calledOnContractWith.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from '../MockProviderCases'; 2 | import {calledOnContractWithTest} from './calledOnContractWithTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: calledOnContractWith', (provider) => { 5 | calledOnContractWithTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/chaining.test.ts: -------------------------------------------------------------------------------- 1 | import {chainingMatchersTest} from './chainingTest'; 2 | import {describeMockProviderCases} from './MockProviderCases'; 3 | 4 | describeMockProviderCases('INTEGRATION: chaining matchers', (provider) => { 5 | chainingMatchersTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/changeEtherBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {changeEtherBalanceTest} from './changeEtherBalanceTest'; 2 | import {BASE_FEE_PER_GAS, TX_GAS} from './constants'; 3 | import {describeMockProviderCases} from './MockProviderCases'; 4 | 5 | describeMockProviderCases('INTEGRATION: changeEtherBalance matcher', (provider) => { 6 | changeEtherBalanceTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS}); 7 | }); 8 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/changeEtherBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {changeEtherBalancesTest} from './changeEtherBalancesTest'; 2 | import {TX_GAS, BASE_FEE_PER_GAS} from './constants'; 3 | import {describeMockProviderCases} from './MockProviderCases'; 4 | 5 | describeMockProviderCases('INTEGRATION: changeEtherBalances matcher', (provider) => { 6 | changeEtherBalancesTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS}); 7 | }); 8 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/changeTokenBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from './MockProviderCases'; 2 | import {changeTokenBalanceTest} from './changeTokenBalanceTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: changeTokenBalance matcher', (provider) => { 5 | changeTokenBalanceTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/changeTokenBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from './MockProviderCases'; 2 | import {changeTokenBalancesTest} from './changeTokenBalancesTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: changeTokenBalances matcher', (provider) => { 5 | changeTokenBalancesTest(provider); 6 | }); 7 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/constants.ts: -------------------------------------------------------------------------------- 1 | export const TX_GAS = 21000; // Gas used by a single, non-contract transaction. 2 | 3 | /** 4 | * Hardfork London - baseFeePerGas is replacing gasPrice. 5 | * A default minimum in Ganache is this number. 6 | * It cannot be set to 0 at this time. 7 | */ 8 | export const BASE_FEE_PER_GAS = 875000000; 9 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/events.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from './MockProviderCases'; 2 | import {eventsTest, eventsWithNamedArgs} from './eventsTest'; 3 | 4 | describeMockProviderCases('INTEGRATION: Events', (provider) => { 5 | eventsTest(provider); 6 | eventsWithNamedArgs(provider); 7 | }); 8 | -------------------------------------------------------------------------------- /waffle-chai/test/matchers/reverted.test.ts: -------------------------------------------------------------------------------- 1 | import {describeMockProviderCases} from './MockProviderCases'; 2 | import {revertedTest} from './revertedTest'; 3 | import {revertedWithTest} from './revertedWithTest'; 4 | 5 | describeMockProviderCases('INTEGRATION: Matchers: reverted', (provider) => { 6 | revertedTest(provider); 7 | }); 8 | 9 | describeMockProviderCases('INTEGRATION: Matchers: revertedWith', (provider) => { 10 | revertedWithTest(provider); 11 | }); 12 | -------------------------------------------------------------------------------- /waffle-chai/test/test-setup.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import {waffleChai} from '../src'; 4 | 5 | chai.use(chaiAsPromised); 6 | chai.use(waffleChai); 7 | -------------------------------------------------------------------------------- /waffle-chai/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-chai/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-provider" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /waffle-cli/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-cli/.gitignore: -------------------------------------------------------------------------------- 1 | /**/build/ 2 | /cache -------------------------------------------------------------------------------- /waffle-cli/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-cli/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | .eslintrc.js 4 | .gitignore 5 | buildTestContracts.ts 6 | tsconfig.build.json 7 | tsconfig.json 8 | -------------------------------------------------------------------------------- /waffle-cli/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-cli/bin/waffle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | const Waffle = require('../dist/cjs/src/cli.js'); 5 | Waffle 6 | .runCli(process.argv.slice(2)) 7 | .catch(e => { 8 | console.error(e); 9 | process.exit(1); 10 | }); 11 | -------------------------------------------------------------------------------- /waffle-cli/buildTestContracts.ts: -------------------------------------------------------------------------------- 1 | import { 2 | compileAndSave, 3 | generateTypes, 4 | inputToConfig 5 | } from '@ethereum-waffle/compiler'; 6 | 7 | const buildExampleContracts = async () => { 8 | console.log('Building example contracts...'); 9 | const sourceDirectory = './test/projects/example'; 10 | const outputDirectory = './test/example/build'; 11 | const flattenOutputDirectory = './test/example/flatten'; 12 | const nodeModulesDirectory = 'node_modules'; 13 | const compilerVersion = 'v0.5.9+commit.e560f70d'; 14 | await compileAndSave({ 15 | sourceDirectory, 16 | outputDirectory, 17 | flattenOutputDirectory, 18 | nodeModulesDirectory, 19 | compilerVersion 20 | }); 21 | }; 22 | const buildExampleTypes = async () => { 23 | console.log('Building example types...'); 24 | await generateTypes( 25 | inputToConfig({ 26 | outputDirectory: './test/example/build', 27 | typechainEnabled: true, 28 | typechainOutputDir: '../../../build' 29 | }) 30 | ); 31 | }; 32 | 33 | (async function () { 34 | await buildExampleContracts(); 35 | await buildExampleTypes(); 36 | })().catch(console.error); 37 | -------------------------------------------------------------------------------- /waffle-cli/src/ContractJSON.ts: -------------------------------------------------------------------------------- 1 | export interface StandardContractJSON { 2 | abi: any; 3 | evm: {bytecode: {object: any}}; 4 | } 5 | 6 | export interface SimpleContractJSON { 7 | abi: any[]; 8 | bytecode: string; 9 | } 10 | 11 | export type ContractJSON = StandardContractJSON | SimpleContractJSON; 12 | 13 | export const isStandard = (data: ContractJSON): data is StandardContractJSON => 14 | typeof (data as any).evm === 'object' && 15 | (data as any).evm !== null && 16 | typeof (data as any).evm.bytecode === 'object' && 17 | (data as any).evm.bytecode !== null; 18 | 19 | export function hasByteCode(bytecode: {object: any} | string) { 20 | if (typeof bytecode === 'object') { 21 | return Object.entries(bytecode.object).length !== 0; 22 | } 23 | return Object.entries(bytecode).length !== 0; 24 | } 25 | -------------------------------------------------------------------------------- /waffle-cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@ethereum-waffle/provider'; 2 | export {waffleChai as solidity} from '@ethereum-waffle/chai'; 3 | export {link} from '@ethereum-waffle/compiler'; 4 | export * from '@ethereum-waffle/mock-contract'; 5 | export * from './deployContract'; 6 | -------------------------------------------------------------------------------- /waffle-cli/test/deployTypedContract.ts: -------------------------------------------------------------------------------- 1 | import {parseEther} from 'ethers/lib/utils'; 2 | import {BasicTokenMock, BasicTokenMock__factory} from '../build'; 3 | import {deployContract, MockProvider} from '../src'; 4 | import {expect} from 'chai'; 5 | 6 | describe('INTEGRATION: deployTypedContract', () => { 7 | const [wallet] = new MockProvider().getWallets(); 8 | 9 | it('successfully deploys contract', async () => { 10 | const contract: BasicTokenMock = await deployContract(wallet, 11 | BasicTokenMock__factory, 12 | [wallet.address, parseEther('100')] 13 | ); 14 | expect(await contract.balanceOf(wallet.address)).to.eq(parseEther('100')); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /waffle-cli/test/example/fixtures-example.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {loadFixture, deployContract, MockProvider} from '../../src'; 3 | import {Wallet} from 'ethers'; 4 | import BasicTokenMock from './build/BasicTokenMock.json'; 5 | 6 | describe('INTEGRATION: Fixtures example', () => { 7 | async function fixture([wallet, other]: Wallet[], provider: MockProvider) { 8 | const token = await deployContract(wallet, BasicTokenMock, [ 9 | wallet.address, 1000 10 | ]); 11 | return {token, wallet, other}; 12 | } 13 | 14 | it('Assigns initial balance', async () => { 15 | const {token, wallet} = await loadFixture(fixture); 16 | expect(await token.balanceOf(wallet.address)).to.equal(1000); 17 | }); 18 | 19 | it('Transfer adds amount to destination account', async () => { 20 | const {token, other} = await loadFixture(fixture); 21 | await token.transfer(other.address, 7); 22 | expect(await token.balanceOf(other.address)).to.equal(7); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /waffle-cli/test/index.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import {waffleChai} from '@ethereum-waffle/chai'; 4 | 5 | chai.use(chaiAsPromised); 6 | chai.use(waffleChai); 7 | -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "./ERC20Basic.sol"; 4 | import "./SafeMath.sol"; 5 | 6 | 7 | /** 8 | * @title Basic token 9 | * @dev Basic version of StandardToken, with no allowances. 10 | */ 11 | contract BasicToken is ERC20Basic { 12 | using SafeMath for uint256; 13 | 14 | mapping(address => uint256) balances; 15 | 16 | uint256 totalSupply_; 17 | 18 | /** 19 | * @dev Total number of tokens in existence 20 | */ 21 | function totalSupply() public view returns (uint256) { 22 | return totalSupply_; 23 | } 24 | 25 | /** 26 | * @dev Transfer token for a specified address 27 | * @param _to The address to transfer to. 28 | * @param _value The amount to be transferred. 29 | */ 30 | function transfer(address _to, uint256 _value) public returns (bool) { 31 | require(_to != address(0), "Invalid address 0x"); 32 | require(_value <= balances[msg.sender], "Not enough balance on sender account"); 33 | 34 | balances[msg.sender] = balances[msg.sender].sub(_value); 35 | balances[_to] = balances[_to].add(_value); 36 | emit Transfer(msg.sender, _to, _value); 37 | return true; 38 | } 39 | 40 | /** 41 | * @dev Gets the balance of the specified address. 42 | * @param _owner The address to query the the balance of. 43 | * @return An uint256 representing the amount owned by the passed address. 44 | */ 45 | function balanceOf(address _owner) public view returns (uint256) { 46 | return balances[_owner]; 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/Check.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | contract Check { 4 | 5 | uint public x; 6 | 7 | constructor () public { 8 | x = 1; 9 | } 10 | 11 | function change() public { 12 | x += 1; 13 | } 14 | } -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/ERC20Basic.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | /** 5 | * @title ERC20Basic 6 | * @dev Simpler version of ERC20 interface 7 | * See https://github.com/ethereum/EIPs/issues/179 8 | */ 9 | contract ERC20Basic { 10 | function totalSupply() public view returns (uint256); 11 | function balanceOf(address who) public view returns (uint256); 12 | function transfer(address to, uint256 value) public returns (bool); 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | } -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/LibraryConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | import "./MyLibrary.sol"; 3 | 4 | 5 | contract LibraryConsumer { 6 | using MyLibrary for uint; 7 | 8 | function useLibrary(uint _number) public pure returns (uint) { 9 | return _number.sevenify(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | /** 5 | * @title SafeMath 6 | * @dev Math operations with safety checks that throw on error 7 | */ 8 | library SafeMath { 9 | 10 | /** 11 | * @dev Multiplies two numbers, throws on overflow. 12 | */ 13 | function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { 14 | // Gas optimization: this is cheaper than asserting 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (_a == 0) { 18 | return 0; 19 | } 20 | 21 | c = _a * _b; 22 | assert(c / _a == _b); 23 | return c; 24 | } 25 | 26 | /** 27 | * @dev Integer division of two numbers, truncating the quotient. 28 | */ 29 | function div(uint256 _a, uint256 _b) internal pure returns (uint256) { 30 | // assert(_b > 0); // Solidity automatically throws when dividing by 0 31 | // uint256 c = _a / _b; 32 | // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold 33 | return _a / _b; 34 | } 35 | 36 | /** 37 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 38 | */ 39 | function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { 40 | assert(_b <= _a); 41 | return _a - _b; 42 | } 43 | 44 | /** 45 | * @dev Adds two numbers, throws on overflow. 46 | */ 47 | function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { 48 | c = _a + _b; 49 | assert(c >= _a); 50 | return c; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/mock/BasicTokenMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; 4 | 5 | 6 | // Example class - a mock class using delivering from ERC20 7 | contract BasicTokenMock is ERC20 { 8 | constructor(address initialAccount, uint256 initialBalance) public { 9 | super._mint(initialAccount, initialBalance); 10 | } 11 | } -------------------------------------------------------------------------------- /waffle-cli/test/projects/example/readme.md: -------------------------------------------------------------------------------- 1 | This file is used in a test. Do not delete. -------------------------------------------------------------------------------- /waffle-cli/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-compiler" 12 | }, 13 | { 14 | "path": "../waffle-mock-contract" 15 | }, 16 | { 17 | "path": "../waffle-provider" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /waffle-compiler/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-compiler/.gitignore: -------------------------------------------------------------------------------- 1 | /**/custom_build 2 | /**/build 3 | /test/flattener/flattenFiles 4 | /cache 5 | test/projects/**/cache -------------------------------------------------------------------------------- /waffle-compiler/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-compiler/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | .eslintrc.js 4 | tsconfig.build.json 5 | tsconfig.json 6 | -------------------------------------------------------------------------------- /waffle-compiler/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/compiler 2 | 3 | ## 4.0.3 4 | 5 | ### Patch Changes 6 | 7 | - a0f721a: Move ethers to peer deps 8 | 9 | ## 4.0.2 10 | 11 | ### Patch Changes 12 | 13 | - 00e9f1b: 🪵 Upgrade solc 14 | 15 | ## 4.0.1 16 | 17 | ### Patch Changes 18 | 19 | - e8adce7: 🧼 Add src folders to npm 20 | - be6fd8e: 🔝 Update ethers to 5.6.2 21 | - Exit prerelease 22 | 23 | ## 4.0.0-alpha.21 24 | 25 | ### Patch Changes 26 | 27 | - e8adce7: 🧼 Add src folders to npm 28 | 29 | ## 4.0.0-alpha.20 30 | 31 | ### Patch Changes 32 | 33 | - be6fd8e: 🔝 Update ethers to 5.6.2 34 | 35 | ## 4.0.0-alpha.1 36 | 37 | ### Patch Changes 38 | 39 | - 4c4b2d6: v4.0.0-alpha.1 40 | 41 | ## 4.0.0-alpha.0 42 | 43 | ### Major Changes 44 | 45 | - Bump typechain and ethers to the latest versions. Move them to peer deps. 46 | 47 | ## 3.4.0 48 | 49 | ### Minor Changes 50 | 51 | - 80d215b: - Fix vulnerabilities shown by `yarn audit` 52 | - Fix typings in `closeTo` matcher 53 | - Add `flattenSingleFile` function to compiler 54 | 55 | ## 3.3.1 56 | 57 | ### Patch Changes 58 | 59 | - 8f5699f: Fix how flattener handles sol imports 60 | 61 | ## 3.3.0 62 | 63 | ### Minor Changes 64 | 65 | - 1d7b466: Fix changeTokenBalance and changeTokenBalances matchers for contracts with overloaded balanceOf 66 | 67 | New matchers for BigNumber: within and closeTo 68 | 69 | Typechain integration 70 | 71 | Fix revertedWith functionality 72 | 73 | ### Patch Changes 74 | 75 | - 246281f: Allow contract deployment using TypeChain-generated types 76 | -------------------------------------------------------------------------------- /waffle-compiler/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-compiler/src/compileDockerSolc.ts: -------------------------------------------------------------------------------- 1 | import {join} from 'path'; 2 | import {Config} from './config'; 3 | import {getCompilerInput} from './compilerInput'; 4 | import {ImportFile} from '@resolver-engine/imports'; 5 | import {executeCommand} from './executeCommand'; 6 | 7 | const CONTAINER_PATH = '/home/project'; 8 | const NPM_PATH = '/home/npm'; 9 | 10 | export function compileDockerSolc(config: Config) { 11 | return async function compile(sources: ImportFile[]) { 12 | const command = createBuildCommand(config); 13 | const input = getCompilerInput(sources, config.compilerOptions, 'Solidity'); 14 | const output = await executeCommand(command, input); 15 | return JSON.parse(output); 16 | }; 17 | } 18 | 19 | export function createBuildCommand(config: Config) { 20 | const tag = config.compilerVersion || 'stable'; 21 | const allowedPaths = `"${CONTAINER_PATH},${NPM_PATH}"`; 22 | return `docker run ${getVolumes(config)} -i -a stdin -a stdout ` + 23 | `ethereum/solc:${tag} --standard-json --allow-paths ${allowedPaths}`; 24 | } 25 | 26 | export function getVolumes(config: Config) { 27 | const hostPath = process.cwd(); 28 | const hostNpmPath = join(hostPath, config.nodeModulesDirectory); 29 | return `-v ${hostPath}:${CONTAINER_PATH} -v ${hostNpmPath}:${NPM_PATH}`; 30 | } 31 | -------------------------------------------------------------------------------- /waffle-compiler/src/compileDockerVyper.ts: -------------------------------------------------------------------------------- 1 | import {Config} from './config'; 2 | import {ImportFile} from '@resolver-engine/imports'; 3 | import {getCompilerInput} from './compilerInput'; 4 | import {executeCommand} from './executeCommand'; 5 | 6 | const CONTAINER_PATH = '/project'; 7 | 8 | export function compileDockerVyper(config: Config) { 9 | return async function compile(sources: ImportFile[]) { 10 | const command = createBuildCommand(config); 11 | const input = getCompilerInput(sources, config.compilerOptions, 'Vyper'); 12 | const output = await executeCommand(command, input); 13 | return JSON.parse(output); 14 | }; 15 | } 16 | 17 | export function createBuildCommand(config: Config) { 18 | const tag = config.compilerVersion || 'stable'; 19 | const volumes = `-v ${process.cwd()}:${CONTAINER_PATH}`; 20 | return `docker run ${volumes} -i -a stdin -a stdout ` + 21 | `-w ${CONTAINER_PATH} --entrypoint vyper-json vyperlang/vyper:${tag}`; 22 | } 23 | -------------------------------------------------------------------------------- /waffle-compiler/src/compileNativeSolc.ts: -------------------------------------------------------------------------------- 1 | import {resolve} from 'path'; 2 | import {Config} from './config'; 3 | import {getCompilerInput} from './compilerInput'; 4 | import {ImportFile} from '@resolver-engine/imports'; 5 | import {executeCommand} from './executeCommand'; 6 | 7 | export function compileNativeSolc(config: Config) { 8 | return async function compile(sources: ImportFile[]) { 9 | const command = createBuildCommand(config); 10 | const input = getCompilerInput(sources, config.compilerOptions, 'Solidity'); 11 | const output = await executeCommand(command, input); 12 | return JSON.parse(output); 13 | }; 14 | } 15 | 16 | export function createBuildCommand(config: Config) { 17 | const command = 'solc'; 18 | const params = '--standard-json'; 19 | const customAllowedPaths = config.compilerAllowedPaths 20 | .map((path: string) => resolve(path)); 21 | const allowedPaths = [ 22 | resolve(config.sourceDirectory), 23 | resolve(config.nodeModulesDirectory), 24 | ...customAllowedPaths 25 | ]; 26 | return `${command} ${params} --allow-paths ${allowedPaths.join(',')}`; 27 | } 28 | -------------------------------------------------------------------------------- /waffle-compiler/src/compilerInput.ts: -------------------------------------------------------------------------------- 1 | import {ImportFile} from '@resolver-engine/imports'; 2 | 3 | export function getCompilerInput( 4 | files: ImportFile[], 5 | overrides: any = {}, 6 | language: 'Solidity' | 'Vyper' 7 | ) { 8 | const sources: Record = {}; 9 | for (const file of files) { 10 | sources[file.url] = {content: file.source}; 11 | } 12 | return JSON.stringify({ 13 | language, 14 | sources, 15 | settings: { 16 | outputSelection: {'*': {'*': ['abi', 'evm.bytecode', 'evm.deployedBytecode']}}, 17 | ...overrides 18 | } 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /waffle-compiler/src/config/defaultConfig.ts: -------------------------------------------------------------------------------- 1 | import {Config} from './config'; 2 | 3 | export const defaultConfig: Config = { 4 | sourceDirectory: './contracts', 5 | outputDirectory: './build', 6 | flattenOutputDirectory: './flatten', 7 | nodeModulesDirectory: './node_modules', 8 | cacheDirectory: './cache', 9 | compilerType: 'solcjs', 10 | compilerVersion: 'default', 11 | compilerAllowedPaths: [], 12 | compilerOptions: {}, 13 | outputHumanReadableAbi: false, 14 | outputType: 'multiple', 15 | typechainEnabled: false, 16 | typechainOutputDir: 'types' 17 | }; 18 | -------------------------------------------------------------------------------- /waffle-compiler/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config'; 2 | export * from './defaultConfig'; 3 | export * from './inputToConfig'; 4 | export * from './loadConfig'; 5 | -------------------------------------------------------------------------------- /waffle-compiler/src/config/loadConfig.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import {InputConfig} from './config'; 4 | 5 | export async function loadConfig(configPath?: string): Promise { 6 | if (configPath) { 7 | return require(path.join(process.cwd(), configPath)); 8 | } else if (fs.existsSync('./waffle.json')) { 9 | return require(path.join(process.cwd(), './waffle.json')); 10 | } else { 11 | return {}; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /waffle-compiler/src/executeCommand.ts: -------------------------------------------------------------------------------- 1 | import {exec} from 'child_process'; 2 | 3 | const MAX_BUFFER_SIZE = 4 * 1024 * 1024; // 4 MB 4 | 5 | export async function executeCommand(command: string, input: string) { 6 | return new Promise((resolve, reject) => { 7 | const childProcess = exec( 8 | command, 9 | {maxBuffer: MAX_BUFFER_SIZE}, 10 | (err, stdout) => err ? reject(err) : resolve(stdout) 11 | ); 12 | childProcess.stdin?.write(input); 13 | childProcess.stdin?.end(); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /waffle-compiler/src/findImports.ts: -------------------------------------------------------------------------------- 1 | import {ImportFile} from '@resolver-engine/imports'; 2 | 3 | export function findImports(sources: ImportFile[]) { 4 | return (file: string) => { 5 | const result = sources.find((importFile) => importFile.url === file); 6 | if (result) { 7 | return {contents: result.source}; 8 | } 9 | return {error: `File not found: ${file}`}; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /waffle-compiler/src/findInputs.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import {isDirectory} from './utils'; 4 | 5 | export function findInputs(sourcePath: string, extension: string) { 6 | const stack = [sourcePath]; 7 | const inputFiles: string[] = []; 8 | while (stack.length > 0) { 9 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 10 | const dir = stack.pop()!; 11 | const files = fs.readdirSync(dir); 12 | for (const file of files) { 13 | const filePath = path.join(dir, file); 14 | if (isDirectory(filePath)) { 15 | stack.push(filePath); 16 | } else if (file.endsWith(extension)) { 17 | inputFiles.push(filePath); 18 | } 19 | } 20 | } 21 | return inputFiles; 22 | } 23 | -------------------------------------------------------------------------------- /waffle-compiler/src/generateTypes.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import {runTypeChain, glob} from 'typechain'; 3 | import {Config} from './config'; 4 | 5 | export async function generateTypes(config: Config) { 6 | const cwd = config.outputDirectory; 7 | const allFiles = glob(cwd, ['*.json']); 8 | await runTypeChain({ 9 | cwd, 10 | allFiles, 11 | filesToProcess: allFiles, 12 | target: 'ethers-v5', 13 | outDir: config.typechainOutputDir 14 | }); 15 | return path.join(config.outputDirectory, config.typechainOutputDir); 16 | } 17 | -------------------------------------------------------------------------------- /waffle-compiler/src/getCompileFunction.ts: -------------------------------------------------------------------------------- 1 | import {Config} from './config'; 2 | import {compileSolcjs} from './compileSolcjs'; 3 | import {compileNativeSolc} from './compileNativeSolc'; 4 | import {compileDockerSolc} from './compileDockerSolc'; 5 | import {compileDockerVyper} from './compileDockerVyper'; 6 | 7 | export function getCompileFunction(config: Config) { 8 | switch (config.compilerType) { 9 | case 'solcjs': return compileSolcjs(config); 10 | case 'native': return compileNativeSolc(config); 11 | case 'dockerized-solc': return compileDockerSolc(config); 12 | case 'dockerized-vyper': return compileDockerVyper(config); 13 | default: throw new Error(`Unknown compiler ${config.compilerType}`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /waffle-compiler/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './compiler'; 2 | export * from './flattener'; 3 | export * from './link'; 4 | export * from './generateTypes'; 5 | export {InputConfig as Config, inputToConfig} from './config'; 6 | -------------------------------------------------------------------------------- /waffle-compiler/src/shims/solc.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'solc' { 2 | export interface SolcCompiler { 3 | compile(sources: string, findImports: (...args: any[]) => any): any; 4 | } 5 | export function compile(sources: string, findImports: (...args: any[]) => any): any 6 | 7 | export function setupMethods(solcjs: any): SolcCompiler 8 | 9 | export function loadRemoteVersion( 10 | version: string, 11 | callback: (err?: Error, solc?: SolcCompiler) => void 12 | ): void; 13 | export function version(): string; 14 | } 15 | -------------------------------------------------------------------------------- /waffle-compiler/src/utils.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import {Config} from './config'; 4 | 5 | export const readFileContent = (path: string): string => 6 | fs.readFileSync(path).toString(); 7 | 8 | export const isFile = (filePath: string) => 9 | fs.existsSync(filePath) && fs.lstatSync(filePath).isFile(); 10 | 11 | export const isDirectory = (directoryPath: string) => 12 | fs.existsSync(path.resolve(directoryPath)) && 13 | fs.statSync(path.resolve(directoryPath)).isDirectory(); 14 | 15 | export const getExtensionForCompilerType = (config: Config) => { 16 | return config.compilerType === 'dockerized-vyper' ? '.vy' : '.sol'; 17 | }; 18 | 19 | export const insert = (source: string, insertedValue: string, index: number) => 20 | `${source.slice(0, index)}${insertedValue}${source.slice(index)}`; 21 | 22 | export const removeEmptyDirsRecursively = (directoryPath: string) => { 23 | if (!isDirectory(directoryPath)) { 24 | return; 25 | } 26 | let files = fs.readdirSync(directoryPath); 27 | if (files.length > 0) { 28 | files.forEach((file) => { 29 | const filePath = path.join(directoryPath, file); 30 | removeEmptyDirsRecursively(filePath); 31 | }); 32 | 33 | // Re-evaluate files as after deleting a subdirectory we may have parent directory empty now 34 | files = fs.readdirSync(directoryPath); 35 | } 36 | 37 | if (files.length === 0) { 38 | fs.rmdirSync(directoryPath); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/compileWithTypes.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {removeSync} from 'fs-extra'; 3 | import {join} from 'path'; 4 | import {compileProject} from '../../src'; 5 | import {isFile} from '../../src/utils'; 6 | 7 | describe('E2E: Compile with types', () => { 8 | before(() => { 9 | process.chdir('test/projects/typechain'); 10 | }); 11 | 12 | it('compiles with generation types using typechain', async () => { 13 | await compileProject('config.json'); 14 | const filePath = join('./build/types', 'Constantinople.ts'); 15 | expect(isFile(filePath), `Expected compilation artefact "${filePath}" to exist.`).to.equal(true); 16 | }); 17 | 18 | after(() => { 19 | removeSync('build'); 20 | removeSync('cache'); 21 | process.chdir('../../..'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/compilerOptions.ts: -------------------------------------------------------------------------------- 1 | import fsx from 'fs-extra'; 2 | import {join} from 'path'; 3 | import {expect} from 'chai'; 4 | import {compileProject} from '../../src/compiler'; 5 | import {readFileContent} from '../../src/utils'; 6 | 7 | const configs = [ 8 | 'config.json', 9 | 'config_docker.json', 10 | 'config_native.json' 11 | ]; 12 | 13 | describe('E2E: Compiler options', () => { 14 | before(() => { 15 | process.chdir('test/projects/compilerOptions'); 16 | }); 17 | 18 | beforeEach(() => { 19 | fsx.removeSync('build'); 20 | }); 21 | 22 | for (const config of configs) { 23 | it(`[${config}] compiles using the provided options`, async () => { 24 | await compileProject(config); 25 | 26 | const filePath = join('./build', 'Constantinople.json'); 27 | const content = JSON.parse(readFileContent(filePath)); 28 | expect(content.evm.bytecode.opcodes.includes(' SHL ')).to.equal(true); 29 | }); 30 | } 31 | 32 | after(async () => { 33 | process.chdir('../../..'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/e2e_errors.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import sinon from 'sinon'; 3 | import {readFileContent} from '../../src/utils'; 4 | import {compileProject} from '../../src/compiler'; 5 | 6 | const configurations = [ 7 | './test/projects/invalidContracts/config_solcjs.json', 8 | './test/projects/invalidContracts/config_docker.json', 9 | './test/projects/invalidContracts/config_native.json' 10 | ]; 11 | 12 | describe('E2E: Compiler integration - error messages', () => { 13 | for (const configurationPath of configurations) { 14 | const configuration = JSON.parse(readFileContent(configurationPath)); 15 | 16 | it(configuration.name, async () => { 17 | const consoleError = console.error; 18 | console.error = sinon.spy(); 19 | 20 | const expectedPattern = /invalid\.sol.*Identifier not found or not.*/; 21 | 22 | const promise = compileProject(configurationPath); 23 | await expect(promise).to.be.rejectedWith(Error, 'Compilation failed'); 24 | expect(console.error).to.be.calledWith(sinon.match(expectedPattern)); 25 | 26 | console.error = consoleError; 27 | }); 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/findImports.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {findImports} from '../../src/findImports'; 3 | import {readFileContent} from '../../src/utils'; 4 | import {ImportFile} from '@resolver-engine/imports'; 5 | 6 | const DATA: ImportFile[] = [ 7 | { 8 | url: '/tmp/waffle/b', 9 | source: 'content of b.sol', 10 | provider: 'unknown' 11 | }, 12 | { 13 | url: 'test/projects/example/BasicToken.sol', 14 | source: readFileContent('test/projects/example/BasicToken.sol'), 15 | provider: 'unkown' 16 | } 17 | ]; 18 | 19 | describe('INTEGRATION: findImports', () => { 20 | DATA.forEach((importFile) => { 21 | it(`correctly finds ${importFile.url}`, async () => { 22 | const result = findImports(DATA)(importFile.url); 23 | expect(result).to.be.deep.equal({contents: importFile.source}); 24 | }); 25 | }); 26 | 27 | it('findImports file not found', async () => { 28 | const result = findImports(DATA)('random/nonexisting.sol'); 29 | expect(result).to.deep.equal({error: 'File not found: random/nonexisting.sol'}); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/findInputs.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | import {expect} from 'chai'; 3 | import {findInputs} from '../../src/findInputs'; 4 | 5 | describe('INTEGRATION: findInputs', () => { 6 | before(async () => { 7 | await fs.mkdirp('/tmp/waffle/a'); 8 | await fs.mkdirp('/tmp/waffle/b'); 9 | await fs.mkdirp('/tmp/waffle/d'); 10 | await fs.mkdirp('/tmp/waffle/c/c'); 11 | 12 | await fs.writeFile('/tmp/waffle/b/b.sol', ''); 13 | await fs.writeFile('/tmp/waffle/d/d.vy', ''); 14 | await fs.writeFile('/tmp/waffle/b/xxx.xxx', ''); 15 | await fs.writeFile('/tmp/waffle/c/c1.sol', ''); 16 | await fs.writeFile('/tmp/waffle/c/c/c2.sol', ''); 17 | }); 18 | 19 | after(async () => { 20 | await fs.remove('/tmp/waffle'); 21 | }); 22 | 23 | it('returns empty array for an empty forlder', () => { 24 | const result = findInputs('/tmp/waffle/a', '.sol'); 25 | expect(result).to.deep.equal([]); 26 | }); 27 | 28 | it('only returns .sol files', () => { 29 | const result = findInputs('/tmp/waffle/b', '.sol'); 30 | expect(result).to.deep.equal([ 31 | '/tmp/waffle/b/b.sol' 32 | ]); 33 | }); 34 | 35 | it('only returns .vy files', () => { 36 | const result = findInputs('/tmp/waffle/d', '.vy'); 37 | expect(result).to.deep.equal([ 38 | '/tmp/waffle/d/d.vy' 39 | ]); 40 | }); 41 | 42 | it('returns files found in a folder recursively', () => { 43 | const result = findInputs('/tmp/waffle/c', '.sol'); 44 | expect(result).to.deep.equal([ 45 | '/tmp/waffle/c/c1.sol', 46 | '/tmp/waffle/c/c/c2.sol' 47 | ]); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/wrappers/compileNative.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {createBuildCommand} from '../../../src/compileNativeSolc'; 3 | import {Config} from '../../../src/config'; 4 | 5 | const sourceDirectory = './test/projects/custom/custom_contracts'; 6 | const nodeModulesDirectory = './test/projects/custom/custom_node_modules'; 7 | const compilerAllowedPaths: string[] = []; 8 | const config = { 9 | sourceDirectory, 10 | nodeModulesDirectory, 11 | compilerAllowedPaths 12 | } as Config; 13 | 14 | describe('UNIT: compileNative', () => { 15 | it('buildCommand', async () => { 16 | const actualCommand = createBuildCommand(config); 17 | const expectedCommand = 'solc --standard-json --allow-paths ' + 18 | '.*test/projects/custom/custom_contracts,.*/test/projects/custom/custom_node_modules'; 19 | expect(actualCommand).to.match(new RegExp(expectedCommand)); 20 | }); 21 | 22 | it('buildCommand with custom allow_paths', async () => { 23 | const actualCommand = createBuildCommand({ 24 | ...config, 25 | compilerAllowedPaths: ['some/random/path', './yet/another/path'] 26 | }); 27 | const expectedCommand = 'solc --standard-json --allow-paths ' + 28 | '.*test/projects/custom/custom_contracts,.*/test/projects/custom/custom_node_modules' + 29 | ',.*/some/random/path.*/yet/another/path'; 30 | expect(actualCommand).to.match(new RegExp(expectedCommand)); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /waffle-compiler/test/compiler/wrappers/saveOutput.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import sinon from 'sinon'; 3 | import {readFileContent} from '../../../src/utils'; 4 | import {saveOutput} from '../../../src/saveOutput'; 5 | import {Config} from '../../../src/config'; 6 | 7 | const sourceDirectory = './test/projects/custom/custom_contracts'; 8 | const nodeModulesDirectory = './test/projects/custom/custom_node_modules'; 9 | const outputDirectory = './buildtmp'; 10 | const config = { 11 | sourceDirectory, 12 | nodeModulesDirectory, 13 | outputDirectory 14 | }; 15 | 16 | describe('UNIT: saveOutput', () => { 17 | it('calls the required fs methods', async () => { 18 | const fsOps = { 19 | writeFile: sinon.spy(), 20 | createDirectory: sinon.spy() 21 | }; 22 | const output = JSON.parse(readFileContent('./test/compiler/wrappers/compilerOutput.json')); 23 | await saveOutput(output, config as Config, fsOps); 24 | const expectedContent = JSON.stringify(output.contracts['One.sol'].One, null, 2); 25 | expect(fsOps.createDirectory).to.be.calledWith('./buildtmp'); 26 | expect(fsOps.writeFile).to.be.calledWith('buildtmp/One.json', expectedContent); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/child.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.4.24 <0.6.0; 3 | 4 | import "openzeppelin-solidity/contracts/access/Roles.sol"; 5 | import "./parent.sol"; 6 | import "openzeppelin-solidity/contracts/access/roles/PauserRole.sol"; 7 | import "./directives.sol"; 8 | 9 | contract Child { 10 | mapping(address => uint256) balances; 11 | } 12 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/cycle1.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.5.2; 3 | 4 | import "./cycle2.sol"; 5 | 6 | contract Cycle1 { 7 | mapping(address => uint256) balances; 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/cycle2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.5.2; 3 | 4 | import "./cycle1.sol"; 5 | 6 | contract Cycle2 { 7 | mapping(address => uint256) balances; 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/directives.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.4.24 <0.6.0; 3 | 4 | import "./directivesImport.sol"; 5 | import "./directivesImport.sol"; 6 | import "./directivesImport.sol"; 7 | import{symbol1 as alias, symbol2} from "directivesImport.sol"; 8 | 9 | /** 10 | * IMPORTANT! the issue as in #422 11 | */ 12 | contract Directives { 13 | struct Import { 14 | bool isImported; 15 | } 16 | 17 | function importData(address source) public { 18 | imports = uint[]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/directivesImport.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity >=0.4.24 <0.6.0; 3 | 4 | contract DirectivesImport {} 5 | -------------------------------------------------------------------------------- /waffle-compiler/test/flattener/testSource/parent.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.5.2; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "openzeppelin-solidity/contracts/access/Roles.sol"; 6 | import "./cycle2.sol"; 7 | 8 | contract Parent { 9 | uint public x; 10 | 11 | constructor () public { 12 | x = 1; 13 | } 14 | 15 | function change() public { 16 | x += 1; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /waffle-compiler/test/index.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import chaiString from 'chai-string'; 4 | import sinonChai from 'sinon-chai'; 5 | import {waffleChai} from '@ethereum-waffle/chai'; 6 | 7 | chai.use(chaiAsPromised); 8 | chai.use(chaiString); 9 | chai.use(sinonChai); 10 | chai.use(waffleChai); 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/compilerOptions/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "evmVersion": "constantinople" 4 | }, 5 | "compilerVersion": "0.5.9" 6 | } 7 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/compilerOptions/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "evmVersion": "constantinople" 4 | }, 5 | "compilerType": "dockerized-solc", 6 | "compilerVersion": "0.5.9" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/compilerOptions/config_native.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "evmVersion": "constantinople" 4 | }, 5 | "compilerType": "native" 6 | } 7 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/compilerOptions/contracts/Constantinople.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract Constantinople { 5 | function constantinople() public pure returns (uint8) { 6 | uint8 a = 0; 7 | /* solium-disable-next-line */ 8 | assembly { 9 | a := shl(1, 2) // SHL is only available in constantinople 10 | } 11 | return a; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/defaultConfigFile/contracts/AmIRichAlready.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.2; 2 | 3 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 | 5 | contract BasicToken is ERC20 { 6 | constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { 7 | _mint(msg.sender, initialBalance); 8 | } 9 | } 10 | 11 | contract AmIRichAlready { 12 | BasicToken private tokenContract; 13 | uint private constant RICHNESS = 1000000 * 10 ** 18; 14 | constructor (BasicToken _tokenContract) public { 15 | tokenContract = _tokenContract; 16 | } 17 | 18 | function check() public view returns (bool) { 19 | uint balance = tokenContract.balanceOf(msg.sender); 20 | return balance > RICHNESS; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/defaultConfigFile/waffle.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.6.2", 4 | "sourceDirectory": "./contracts", 5 | "outputDirectory": "./build", 6 | "outputType": "minimal" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "./ERC20Basic.sol"; 4 | import "./SafeMath.sol"; 5 | 6 | 7 | /** 8 | * @title Basic token 9 | * @dev Basic version of StandardToken, with no allowances. 10 | */ 11 | contract BasicToken is ERC20Basic { 12 | using SafeMath for uint256; 13 | 14 | mapping(address => uint256) balances; 15 | 16 | uint256 totalSupply_; 17 | 18 | /** 19 | * @dev Total number of tokens in existence 20 | */ 21 | function totalSupply() public view returns (uint256) { 22 | return totalSupply_; 23 | } 24 | 25 | /** 26 | * @dev Transfer token for a specified address 27 | * @param _to The address to transfer to. 28 | * @param _value The amount to be transferred. 29 | */ 30 | function transfer(address _to, uint256 _value) public returns (bool) { 31 | require(_to != address(0), "Invalid address 0x"); 32 | require(_value <= balances[msg.sender], "Not enough balance on sender account"); 33 | 34 | balances[msg.sender] = balances[msg.sender].sub(_value); 35 | balances[_to] = balances[_to].add(_value); 36 | emit Transfer(msg.sender, _to, _value); 37 | return true; 38 | } 39 | 40 | /** 41 | * @dev Gets the balance of the specified address. 42 | * @param _owner The address to query the the balance of. 43 | * @return An uint256 representing the amount owned by the passed address. 44 | */ 45 | function balanceOf(address _owner) public view returns (uint256) { 46 | return balances[_owner]; 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/Check.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | contract Check { 4 | 5 | uint public x; 6 | 7 | constructor () public { 8 | x = 1; 9 | } 10 | 11 | function change() public { 12 | x += 1; 13 | } 14 | } -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/ERC20Basic.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | /** 5 | * @title ERC20Basic 6 | * @dev Simpler version of ERC20 interface 7 | * See https://github.com/ethereum/EIPs/issues/179 8 | */ 9 | contract ERC20Basic { 10 | function totalSupply() public view returns (uint256); 11 | function balanceOf(address who) public view returns (uint256); 12 | function transfer(address to, uint256 value) public returns (bool); 13 | event Transfer(address indexed from, address indexed to, uint256 value); 14 | } -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/LibraryConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | import "./MyLibrary.sol"; 3 | 4 | 5 | contract LibraryConsumer { 6 | using MyLibrary for uint; 7 | 8 | function useLibrary(uint _number) public pure returns (uint) { 9 | return _number.sevenify(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | /** 5 | * @title SafeMath 6 | * @dev Math operations with safety checks that throw on error 7 | */ 8 | library SafeMath { 9 | 10 | /** 11 | * @dev Multiplies two numbers, throws on overflow. 12 | */ 13 | function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { 14 | // Gas optimization: this is cheaper than asserting 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (_a == 0) { 18 | return 0; 19 | } 20 | 21 | c = _a * _b; 22 | assert(c / _a == _b); 23 | return c; 24 | } 25 | 26 | /** 27 | * @dev Integer division of two numbers, truncating the quotient. 28 | */ 29 | function div(uint256 _a, uint256 _b) internal pure returns (uint256) { 30 | // assert(_b > 0); // Solidity automatically throws when dividing by 0 31 | // uint256 c = _a / _b; 32 | // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold 33 | return _a / _b; 34 | } 35 | 36 | /** 37 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 38 | */ 39 | function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { 40 | assert(_b <= _a); 41 | return _a - _b; 42 | } 43 | 44 | /** 45 | * @dev Adds two numbers, throws on overflow. 46 | */ 47 | function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { 48 | c = _a + _b; 49 | assert(c >= _a); 50 | return c; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/mock/BasicTokenMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; 4 | 5 | 6 | // Example class - a mock class using delivering from ERC20 7 | contract BasicTokenMock is ERC20 { 8 | constructor(address initialAccount, uint256 initialBalance) public { 9 | super._mint(initialAccount, initialBalance); 10 | } 11 | } -------------------------------------------------------------------------------- /waffle-compiler/test/projects/example/readme.md: -------------------------------------------------------------------------------- 1 | This file is used in a test. Do not delete. -------------------------------------------------------------------------------- /waffle-compiler/test/projects/humanReadableAbi/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "outputHumanReadableAbi": true, 3 | "compilerVersion": "0.6.3" 4 | } 5 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/humanReadableAbi/config2.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerVersion": "0.6.3" 3 | } 4 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/humanReadableAbi/contracts/MyContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.0; 2 | pragma experimental ABIEncoderV2; 3 | 4 | contract MyContract { 5 | struct Baz { 6 | string a; 7 | InnerBaz b; 8 | bool[] nested; 9 | } 10 | 11 | struct InnerBaz { 12 | uint b; 13 | } 14 | 15 | event FooEvent (); 16 | event Bar (bool argOne, uint indexed argTwo); 17 | 18 | uint200 boo; 19 | constructor (uint argOne) public { 20 | boo = uint200(argOne); 21 | } 22 | 23 | fallback () external { 24 | } 25 | 26 | function noArgs() public view returns (uint200) { 27 | return boo; 28 | } 29 | 30 | function oneArg(bool argOne) public { 31 | boo = argOne ? 1 : 0; 32 | } 33 | 34 | function twoReturns(bool argOne) public view returns (bool, uint) { 35 | return (argOne, boo); 36 | } 37 | 38 | function threeArgs(string memory argOne, bool argTwo, uint[] memory argThree) public view returns (bool, uint) { 39 | argOne; 40 | argTwo; 41 | return (boo > 1, argThree[1]); 42 | } 43 | 44 | function bar() private returns (uint200) { 45 | return boo++; 46 | } 47 | 48 | function complicated (Baz[] memory items) public returns (Baz memory) { 49 | bar(); 50 | return items[0]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/main/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity 5, dokerized solc, inside out directory structure", 3 | "sourceDirectory": "./contracts", 4 | "outputDirectory": "../build/nested", 5 | "nodeModulesDirectory": "../modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.5.9" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/main/contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/main/contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/main/contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/main/contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/insideOut/modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/invalidContracts/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity 5, dokerized solc, invalid contract", 3 | "sourceDirectory": "./test/projects/invalidContracts", 4 | "outputDirectory": "./test/projects/invalidContracts/custom_build", 5 | "nodeModulesDirectory": "./test/projects/invalidContracts/custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.5.9" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/invalidContracts/config_native.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity 5, native solc, invalid contract", 3 | "sourceDirectory": "./test/projects/invalidContracts", 4 | "outputDirectory": "./test/projects/invalidContracts/custom_build", 5 | "nodeModulesDirectory": "./test/projects/invalidContracts/custom_node_modules", 6 | "compilerType": "native" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/invalidContracts/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity 5, solcjs, invalid contract", 3 | "sourceDirectory": "./test/projects/invalidContracts", 4 | "outputDirectory": "./test/projects/invalidContracts/custom_build", 5 | "nodeModulesDirectory": "./test/projects/invalidContracts/custom_node_modules", 6 | "compilerVersion": "0.5.9" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/invalidContracts/invalid.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract InvalidContract { 5 | 6 | function f(wrongType arg) public { 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /waffle-compiler/test/projects/outputType/config-minimal-humanReadableAbi.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.5.15", 4 | "sourceDirectory": "./contracts", 5 | "outputDirectory": "./build", 6 | "outputType": "minimal", 7 | "outputHumanReadableAbi": true 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/outputType/config-minimal.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerType": "solcjs", 3 | "compilerVersion": "0.5.15", 4 | "sourceDirectory": "./contracts", 5 | "outputDirectory": "./build", 6 | "outputType": "minimal" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/outputType/contracts/Constantinople.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract Constantinople { 5 | function constantinople() public pure returns (uint8) { 6 | uint8 a = 0; 7 | /* solium-disable-next-line */ 8 | assembly { 9 | a := shl(1, 2) // SHL is only available in constantinople 10 | } 11 | return a; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 4 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.4.24" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 4 - solcjs", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "0.4.24" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/config_solcjs_commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 4 - solcjs with commit version", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "v0.4.24+commit.e67f0147" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_node_modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity4/custom_node_modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_commonjs.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'Solidity 5 - commonjs', 3 | sourceDirectory: './custom_contracts', 4 | outputDirectory: './custom_build', 5 | nodeModulesDirectory: './custom_node_modules', 6 | compilerVersion: '0.5.9', 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 5 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.5.9" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_klab.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 5 - KLAB", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "outputType": "all", 7 | "compilerOptions": { 8 | "outputSelection": { 9 | "*": { 10 | "*": [ 11 | "evm.bytecode.object", 12 | "evm.deployedBytecode.object", 13 | "abi", 14 | "evm.bytecode.sourceMap", 15 | "evm.deployedBytecode.sourceMap" 16 | ], 17 | "": [ 18 | "ast" 19 | ] 20 | } 21 | } 22 | }, 23 | "compilerVersion": "0.5.9" 24 | } 25 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_native.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 5 - native", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "native" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_promise.js: -------------------------------------------------------------------------------- 1 | module.exports = Promise.resolve({ 2 | name: 'Solidity 5 - promise', 3 | sourceDirectory: './custom_contracts', 4 | outputDirectory: './custom_build', 5 | nodeModulesDirectory: './custom_node_modules', 6 | compilerVersion: '0.5.9', 7 | }) 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 5 - solcjs", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "0.5.9" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/config_solcjs_commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 5 - solcjs with commit version", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "v0.5.9+commit.e560f70d" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_node_modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity5/custom_node_modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 6 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.6.2" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 6 - solcjs", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "0.6.2" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/config_solcjs_commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 6 - solcjs with commit version", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "v0.6.2+commit.bacdbe57" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_node_modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity6/custom_node_modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.1; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 7 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.7.6" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 7 - solcjs", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "0.7.6" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/config_solcjs_commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 7 - solcjs with commit version", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "v0.7.6+commit.7338295f" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_node_modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity7/custom_node_modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.7.1; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/config_docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 8 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerType": "dockerized-solc", 7 | "compilerVersion": "0.8.15" 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/config_solcjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 8 - solcjs", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "0.8.15" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/config_solcjs_commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Solidity 8 - solcjs with commit version", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "nodeModulesDirectory": "./custom_node_modules", 6 | "compilerVersion": "v0.8.15+commit.e14f2714" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_contracts/Custom.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | import "openzeppelin-solidity/CustomSafeMath.sol"; 4 | 5 | 6 | contract Custom { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_contracts/MyLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | 4 | library MyLibrary { 5 | function sevenify(uint _number) public pure returns (uint) { 6 | return _number + 7; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_contracts/sub/One.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | import "openzeppelin-solidity/sub/ERC20.sol"; 4 | 5 | 6 | contract One { 7 | function dummy() public pure { 8 | 9 | } 10 | } 11 | 12 | 13 | contract OneAndAHalf { 14 | function someOtherDummy() public pure { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_contracts/sub/Two.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | import "./One.sol"; 4 | import "../MyLibrary.sol"; 5 | 6 | 7 | contract Two { 8 | using MyLibrary for uint; 9 | 10 | function dummy() public pure { 11 | 12 | } 13 | 14 | function useLibrary(uint _number) public pure returns (uint) { 15 | return _number.sevenify(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_node_modules/openzeppelin-solidity/CustomSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | 4 | contract CustomSafeMath { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/solidity8/custom_node_modules/openzeppelin-solidity/sub/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.1; 2 | 3 | 4 | contract ERC20 { 5 | function dummy() public pure { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/typechain/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "evmVersion": "constantinople" 4 | }, 5 | "compilerVersion": "0.5.9", 6 | "typechainEnabled": true 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/typechain/contracts/Constantinople.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | 4 | contract Constantinople { 5 | function constantinople() public pure returns (uint8) { 6 | uint8 a = 0; 7 | /* solium-disable-next-line */ 8 | assembly { 9 | a := shl(1, 2) // SHL is only available in constantinople 10 | } 11 | return a; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/vyper0.1/config_vyper_0b15.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vyper 0.1.0b15 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "compilerType": "dockerized-vyper", 6 | "compilerVersion": "0.1.0b15" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/vyper0.1/config_vyper_0b17.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vyper 0.1.0b17 - docker", 3 | "sourceDirectory": "./custom_contracts", 4 | "outputDirectory": "./custom_build", 5 | "compilerType": "dockerized-vyper", 6 | "compilerVersion": "0.1.0b17" 7 | } 8 | -------------------------------------------------------------------------------- /waffle-compiler/test/projects/vyper0.1/custom_contracts/Custom.vy: -------------------------------------------------------------------------------- 1 | name: public(string[64]) 2 | 3 | 4 | @public 5 | def __init__(_name: string[64]): 6 | self.name = _name 7 | -------------------------------------------------------------------------------- /waffle-compiler/test/typegeneration/typechain.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import fsx from 'fs-extra'; 3 | import path from 'path'; 4 | import {compileAndSave} from '../../src'; 5 | import {inputToConfig} from '../../src/config'; 6 | import {generateTypes} from '../../src/generateTypes'; 7 | 8 | const sourceDirectory = './test/projects/example'; 9 | const outputDirectory = './test/projects/build'; 10 | const compilerVersion = 'v0.5.9+commit.e560f70d'; 11 | const config = inputToConfig({ 12 | sourceDirectory, 13 | outputDirectory, 14 | compilerVersion 15 | }); 16 | 17 | describe('Type generation with TypeChain', () => { 18 | it('outputs types to specified directory', async () => { 19 | await compileAndSave(config); 20 | const outputDirectoryForTypes = await generateTypes(config); 21 | expect(outputDirectoryForTypes).to.eq(path.join(config.outputDirectory, 'types')); 22 | const {BasicTokenMock__factory} = await import(path.join('..', '..', outputDirectoryForTypes, 'index.ts')); 23 | expect(BasicTokenMock__factory.name).to.equal('BasicTokenMock__factory'); 24 | expect(Object.getPrototypeOf(BasicTokenMock__factory).name).to.equal('ContractFactory'); 25 | }); 26 | 27 | after(() => { 28 | fsx.removeSync(outputDirectory); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /waffle-compiler/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-compiler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-provider" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /waffle-e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-e2e/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | cache -------------------------------------------------------------------------------- /waffle-e2e/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-e2e/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/e2e 2 | 3 | ## 4.0.2 4 | 5 | ### Patch Changes 6 | 7 | - 00e9f1b: 🪵 Upgrade solc 8 | 9 | ## 4.0.1 10 | 11 | ### Patch Changes 12 | 13 | - be6fd8e: 🔝 Update ethers to 5.6.2 14 | - Exit prerelease 15 | 16 | ## 4.0.0-alpha.20 17 | 18 | ### Patch Changes 19 | 20 | - be6fd8e: 🔝 Update ethers to 5.6.2 21 | 22 | ## 4.0.0-alpha.1 23 | 24 | ### Patch Changes 25 | 26 | - 4c4b2d6: v4.0.0-alpha.1 27 | 28 | ## 4.0.0-alpha.0 29 | 30 | ### Major Changes 31 | 32 | - Bump typechain and ethers to the latest versions. Move them to peer deps. 33 | 34 | ## 1.1.0 35 | 36 | ### Minor Changes 37 | 38 | - 80d215b: - Fix vulnerabilities shown by `yarn audit` 39 | - Fix typings in `closeTo` matcher 40 | - Add `flattenSingleFile` function to compiler 41 | -------------------------------------------------------------------------------- /waffle-e2e/buildTestContracts.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import {compileAndSave} from '@ethereum-waffle/compiler'; 3 | 4 | compileAndSave({ 5 | sourceDirectory: './src', 6 | outputDirectory: './build', 7 | compilerVersion: '0.5.15' 8 | }); 9 | -------------------------------------------------------------------------------- /waffle-e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ethereum-waffle/e2e", 3 | "version": "4.0.2", 4 | "private": true, 5 | "main": "index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "build": "ts-node buildTestContracts", 9 | "test:nobuild": "mocha", 10 | "test": "pnpm build && pnpm test:nobuild", 11 | "lint": "eslint '{src,test}/**/*.ts'", 12 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 13 | }, 14 | "devDependencies": { 15 | "@ethereum-waffle/chai": "workspace:*", 16 | "@ethereum-waffle/compiler": "workspace:*", 17 | "@ethereum-waffle/provider": "workspace:*", 18 | "ethers": "5.6.2", 19 | "solc": "0.8.15", 20 | "typechain": "^8.0.0", 21 | "mocha": "^8.2.1", 22 | "eslint": "^7.14.0", 23 | "ts-node": "^10.0.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /waffle-e2e/src/HelloContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.15; 2 | 3 | contract HelloContract { 4 | event LogHello(); 5 | 6 | function sayHello() external { 7 | emit LogHello(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /waffle-e2e/test/index.ts: -------------------------------------------------------------------------------- 1 | import chai, {expect} from 'chai'; 2 | import {waffleChai} from '@ethereum-waffle/chai'; 3 | 4 | import {MockProvider} from '@ethereum-waffle/provider'; 5 | import {ContractFactory} from 'ethers'; 6 | import HelloContract from '../build/HelloContract.json'; 7 | 8 | chai.use(waffleChai); 9 | 10 | it('deploys contract and emit simple event', async () => { 11 | const [wallet] = new MockProvider().getWallets(); 12 | const factory = new ContractFactory(HelloContract.abi, HelloContract.bytecode, wallet); 13 | const contract = await factory.deploy(); 14 | await expect(contract.sayHello()).to.emit(contract, 'LogHello'); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-compiler" 12 | }, 13 | { 14 | "path": "../waffle-provider" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /waffle-ens/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-ens/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-ens/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-ens/build-artifacts.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | /* eslint-disable @typescript-eslint/no-var-requires */ 3 | 4 | const {promises: fs} = require('fs'); 5 | const path = require('path'); 6 | const ens = require('@ensdomains/ens'); 7 | const resolver = require('@ensdomains/resolver'); 8 | 9 | const outputFolder = './dist/contracts/'; 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-floating-promises 12 | (async () => { 13 | try { 14 | await fs.stat(outputFolder); 15 | } catch (error) { 16 | await fs.mkdir(outputFolder, {recursive: true}); 17 | } 18 | 19 | await writeContracts(ens); 20 | await writeContracts(resolver); 21 | })(); 22 | 23 | async function writeContracts(package) { 24 | for (const key in package) { 25 | await fs.writeFile(path.resolve(outputFolder, `${key}.json`), JSON.stringify(package[key])); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /waffle-ens/src/contracts.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | 3 | const contracts = [ 4 | 'DNSResolver', 5 | 'Deed', 6 | 'DeedImplementation', 7 | 'DefaultReverseResolver', 8 | 'ENS', 9 | 'ENSRegistry', 10 | 'FIFSRegistrar', 11 | 'HashRegistrar', 12 | 'Migrations', 13 | 'OwnedResolver', 14 | 'PublicResolver', 15 | 'Registrar', 16 | 'Resolver', 17 | 'ReverseRegistrar', 18 | 'TestRegistrar' 19 | ]; 20 | 21 | try { 22 | for (const contract of contracts) { 23 | exports[contract] = require(`../contracts/${contract}.json`); 24 | } 25 | } catch (contractsRequireError) { 26 | try { 27 | module.exports = { 28 | ...require('@ensdomains/ens'), 29 | ...require('@ensdomains/resolver') 30 | }; 31 | } catch { 32 | // If the dependencies are missing, a descriptive error is thrown 33 | // when trying to use one of the ENS functions. 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /waffle-ens/src/errors.ts: -------------------------------------------------------------------------------- 1 | export class MissingDomain extends Error { 2 | constructor(domain: string) { 3 | super(`Domain ${domain} doesn't exist.`); 4 | } 5 | } 6 | 7 | export class InvalidDomain extends Error { 8 | constructor(domain: string) { 9 | super(`Invalid domain: '${domain}'`); 10 | } 11 | } 12 | 13 | export class ExpectedTopLevelDomain extends Error { 14 | constructor() { 15 | super('Invalid domain. Please, enter no top level domain.'); 16 | Object.setPrototypeOf(this, ExpectedTopLevelDomain.prototype); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /waffle-ens/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ENS'; 2 | -------------------------------------------------------------------------------- /waffle-ens/src/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module './contracts.js' 2 | -------------------------------------------------------------------------------- /waffle-ens/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {ContractFactory, Signer, utils} from 'ethers'; 2 | import {ExpectedTopLevelDomain, InvalidDomain} from './errors'; 3 | 4 | const {namehash} = utils; 5 | 6 | export const COIN_TYPE_ETH = 60; 7 | 8 | export const deployContract = async (signer: Signer, contractJSON: any, args: Array) => { 9 | const factory = new ContractFactory(contractJSON.abi, contractJSON.bytecode, signer); 10 | return factory.deploy(...args); 11 | }; 12 | 13 | interface ENSDomainInfo { 14 | chunks: string []; 15 | tld: string; 16 | rawLabel: string; 17 | label: string; 18 | node: string; 19 | rootNode: string; 20 | decodedRootNode: string; 21 | } 22 | 23 | export const getDomainInfo = (domain: string): ENSDomainInfo => { 24 | const chunks = domain.split('.'); 25 | const isTopLevelDomain = (chunks.length === 1 && chunks[0].length > 0); 26 | const isEmptyDomain = (domain === ''); 27 | 28 | if (isTopLevelDomain) { 29 | throw new ExpectedTopLevelDomain(); 30 | } else if (isEmptyDomain) { 31 | throw new InvalidDomain(domain); 32 | } 33 | try { 34 | namehash(domain); 35 | } catch (e) { 36 | throw new InvalidDomain(domain); 37 | } 38 | 39 | return { 40 | chunks, 41 | tld: chunks[chunks.length - 1], 42 | rawLabel: chunks[0], 43 | label: utils.id(chunks[0]), 44 | node: namehash(domain), 45 | rootNode: namehash(domain.replace(chunks[0] + '.', '')), 46 | decodedRootNode: domain.replace(chunks[0] + '.', '') 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /waffle-ens/test/utils.test.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {utils} from 'ethers'; 3 | import {getDomainInfo} from '../src/utils'; 4 | 5 | describe('UNIT: getDomainInfo', async () => { 6 | it('third level domain', () => { 7 | expect(getDomainInfo('vlad.ethworks.test')) 8 | .to.deep.include({ 9 | chunks: ['vlad', 'ethworks', 'test'], 10 | tld: 'test', 11 | rawLabel: 'vlad', 12 | label: utils.id('vlad'), 13 | node: utils.namehash('vlad.ethworks.test'), 14 | rootNode: utils.namehash('ethworks.test'), 15 | decodedRootNode: 'ethworks.test' 16 | }); 17 | }); 18 | 19 | it('second level domain', () => { 20 | expect(getDomainInfo('ethworks.test')) 21 | .to.deep.include({ 22 | chunks: ['ethworks', 'test'], 23 | tld: 'test', 24 | rawLabel: 'ethworks', 25 | label: utils.id('ethworks'), 26 | node: utils.namehash('ethworks.test'), 27 | rootNode: utils.namehash('test'), 28 | decodedRootNode: 'test' 29 | }); 30 | }); 31 | 32 | it('top level domain', () => { 33 | expect(() => getDomainInfo('test')) 34 | .to.throw('Invalid domain. Please, enter no top level domain.'); 35 | }); 36 | 37 | it('empty domain', () => { 38 | expect(() => getDomainInfo('')) 39 | .to.throw('Invalid domain: \'\''); 40 | }); 41 | 42 | it('invalid domain', () => { 43 | expect(() => getDomainInfo('vlad..ethworks.test')) 44 | .to.throw('Invalid domain: \'vlad..ethworks.test\''); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /waffle-ens/test/utils.ts: -------------------------------------------------------------------------------- 1 | import {providers, Wallet} from 'ethers'; 2 | import Ganache from 'ganache'; 3 | 4 | export const getWallet = (): Wallet => { 5 | const balance = '0x1ED09BEAD87C0378D8E6400000000'; // 10^34 6 | const secretKey = '0x03c909455dcef4e1e981a21ffb14c1c51214906ce19e8e7541921b758221b5ae'; 7 | 8 | const defaultAccount = [{balance, secretKey}]; 9 | 10 | const ganacheProvider = Ganache.provider({accounts: defaultAccount, logging: {quiet: true}}); 11 | const provider = new providers.Web3Provider(ganacheProvider as any); 12 | return new Wallet(defaultAccount[0].secretKey, provider); 13 | }; 14 | -------------------------------------------------------------------------------- /waffle-ens/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-ens/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "outDir": "dist" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /waffle-hardhat/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-hardhat/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.test.{js,ts}', 6 | file: 'test/test-setup.ts' 7 | } 8 | -------------------------------------------------------------------------------- /waffle-hardhat/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/hardhat 2 | 3 | ## 4.0.4 4 | 5 | ### Patch Changes 6 | 7 | - da92375: Add mock contract deployment at a specified address 8 | - 9602243: 👔 revertedWith().withArgs no longer fails for uint values exceeding JavaScript's max int limit 9 | 10 | ## 4.0.3 11 | 12 | ### Patch Changes 13 | 14 | - 9940630: 🦷 (Experimental) Automatically inject call history into hardhat provider 15 | 16 | ## 4.0.2 17 | 18 | ### Patch Changes 19 | 20 | - 41e809f: Decode revert string in hardhat 2.9.4+ 21 | 22 | ## 4.0.1 23 | 24 | ### Patch Changes 25 | 26 | - be6fd8e: 🔝 Update ethers to 5.6.2 27 | - Exit prerelease 28 | 29 | ## 4.0.0-alpha.20 30 | 31 | ### Patch Changes 32 | 33 | - be6fd8e: 🔝 Update ethers to 5.6.2 34 | 35 | ## 4.0.0-alpha.10 36 | 37 | ### Patch Changes 38 | 39 | - 7a01715: Add package for testing hardhat and waffle integration 40 | -------------------------------------------------------------------------------- /waffle-hardhat/README.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/hardhat 2 | 3 | Package for testing `@nomiclabs/hardhat-waffle` plugin. 4 | -------------------------------------------------------------------------------- /waffle-hardhat/contracts/CustomError.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | 3 | error One(uint value, string msg, bytes32 encoded); 4 | error Two(uint256[3] value, bytes32[2] encoded); 5 | error $__DecoratedCustomErrorName(uint value, string msg, bytes32 encoded); 6 | 7 | contract Matchers { 8 | function doRevertWithOne() public pure { 9 | revert One(0, 'message', 0x00cFBbaF7DDB3a1476767101c12a0162e241fbAD2a0162e2410cFBbaF7162123); 10 | } 11 | 12 | function doRevertWithBigNumber() public pure { 13 | revert One(9007199254740991000000, 'message', 0x00cFBbaF7DDB3a1476767101c12a0162e241fbAD2a0162e2410cFBbaF7162123); 14 | } 15 | 16 | function doRevertWithTwo() public pure { 17 | revert Two( 18 | [ 19 | uint256(1), 20 | uint256(2), 21 | uint256(3) 22 | ], 23 | [ 24 | bytes32(0x00cFBbaF7DDB3a1476767101c12a0162e241fbAD2a0162e2410cFBbaF7162123), 25 | bytes32(0x00cFBbaF7DDB3a1476767101c12a0162e241fbAD2a0162e2410cFBbaF7162124) 26 | ] 27 | ); 28 | } 29 | 30 | function doRevertWithDecoratedCustomErrorName() public pure { 31 | revert $__DecoratedCustomErrorName(0, 'message', 0x00cFBbaF7DDB3a1476767101c12a0162e241fbAD2a0162e2410cFBbaF7162123); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /waffle-hardhat/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import 'hardhat-waffle-dev' 2 | 3 | module.exports = { 4 | networks: { 5 | hardhat: { 6 | initialDate: '2020-01-01T00:00:00', 7 | allowUnlimitedContractSize: true, 8 | }, 9 | }, 10 | paths: { 11 | sources: './contracts', 12 | artifacts: './build', 13 | cache: './cache', 14 | }, 15 | solidity: { 16 | compilers: [ 17 | { 18 | version: "0.8.10" 19 | } 20 | ] 21 | }, 22 | waffle: { 23 | injectCallHistory: true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /waffle-hardhat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ethereum-waffle/hardhat", 3 | "description": "A sweet set of chai matchers for your blockchain testing needs.", 4 | "version": "4.0.4", 5 | "author": "Marek Kirejczyk (http://ethworks.io)", 6 | "repository": "git@github.com:EthWorks/Waffle.git", 7 | "private": true, 8 | "license": "MIT", 9 | "main": "dist/cjs/src/index.js", 10 | "module": "dist/esm/src/index.ts", 11 | "types": "dist/esm/src/index.d.ts", 12 | "scripts": { 13 | "build": "hardhat compile", 14 | "test": "NODE_PATH=\"${PWD}/node_modules\":$NODE_PATH mocha", 15 | "lint": "eslint '{src,test}/**/*.ts'", 16 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'" 17 | }, 18 | "engines": { 19 | "node": ">=10.0" 20 | }, 21 | "devDependencies": { 22 | "@ethereum-waffle/chai": "workspace:*", 23 | "@ethereum-waffle/mock-contract": "workspace:^*", 24 | "@ethereum-waffle/provider": "workspace:*", 25 | "@nomiclabs/hardhat-ethers": "2.1.0", 26 | "@types/node": "^17.0.41", 27 | "eslint": "^7.14.0", 28 | "ethereum-waffle": "workspace:*", 29 | "ethers": "5.6.2", 30 | "hardhat": "2.10.1", 31 | "hardhat-waffle-dev": "2.0.3-dev.c5b5c29", 32 | "mocha": "^8.2.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /waffle-hardhat/test/calledOnContract/calledOnContract.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {calledOnContractTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: calledOnContract', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | beforeEach(() => provider.clearCallHistory()); 13 | 14 | calledOnContractTest(provider); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-hardhat/test/calledOnContract/calledOnContractValidators.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {calledOnContractValidatorsTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: ethCalledValidators', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | beforeEach(() => provider.clearCallHistory()); 13 | 14 | calledOnContractValidatorsTest(provider); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-hardhat/test/calledOnContract/calledOnContractWith.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {calledOnContractWithTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: calledOnContractWith', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | beforeEach(() => provider.clearCallHistory()); 13 | 14 | calledOnContractWithTest(provider); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-hardhat/test/chaining.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {chainingMatchersTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: chaining', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | chainingMatchersTest(provider); 13 | }); 14 | -------------------------------------------------------------------------------- /waffle-hardhat/test/changeEtherBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {changeEtherBalanceTest} from '@ethereum-waffle/chai/test'; 4 | import {TX_GAS, BASE_FEE_PER_GAS} from './constants'; 5 | 6 | describe('INTEGRATION: changeEtherBalance matcher', () => { 7 | const provider = waffle.provider as MockProvider; 8 | 9 | before(async () => { 10 | await provider.send('hardhat_reset', []); 11 | }); 12 | 13 | changeEtherBalanceTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS}); 14 | }); 15 | -------------------------------------------------------------------------------- /waffle-hardhat/test/changeEtherBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {changeEtherBalancesTest} from '@ethereum-waffle/chai/test'; 4 | import {TX_GAS, BASE_FEE_PER_GAS} from './constants'; 5 | 6 | describe('INTEGRATION: changeEtherBalance matcher', () => { 7 | const provider = waffle.provider as MockProvider; 8 | 9 | before(async () => { 10 | await provider.send('hardhat_reset', []); 11 | }); 12 | 13 | changeEtherBalancesTest(provider, {txGasFees: TX_GAS * BASE_FEE_PER_GAS, baseFeePerGas: BASE_FEE_PER_GAS}); 14 | }); 15 | -------------------------------------------------------------------------------- /waffle-hardhat/test/changeTokenBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {changeTokenBalanceTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: changeEtherBalance matcher', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | changeTokenBalanceTest(provider); 13 | }); 14 | -------------------------------------------------------------------------------- /waffle-hardhat/test/changeTokenBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {changeTokenBalancesTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: changeEtherBalance matcher', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | changeTokenBalancesTest(provider); 13 | }); 14 | -------------------------------------------------------------------------------- /waffle-hardhat/test/constants.ts: -------------------------------------------------------------------------------- 1 | export const TX_GAS = 21000; // Gas used by a single, non-contract transaction. 2 | export const BASE_FEE_PER_GAS = 875000000; 3 | -------------------------------------------------------------------------------- /waffle-hardhat/test/events.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {eventsTest} from '@ethereum-waffle/chai/test'; 4 | 5 | describe('INTEGRATION: changeEtherBalance matcher', () => { 6 | const provider = waffle.provider as MockProvider; 7 | 8 | before(async () => { 9 | await provider.send('hardhat_reset', []); 10 | }); 11 | 12 | eventsTest(provider); 13 | }); 14 | -------------------------------------------------------------------------------- /waffle-hardhat/test/mockContract.test.ts: -------------------------------------------------------------------------------- 1 | import {waffle} from 'hardhat'; 2 | import {MockProvider} from 'ethereum-waffle'; 3 | import {mockContractDirectTest} from '@ethereum-waffle/mock-contract/test/directTest'; 4 | import {mockContractProxiedTest} from '@ethereum-waffle/mock-contract/test/proxiedTest'; 5 | 6 | describe('INTEGRATION: Mock Contract', () => { 7 | const provider = waffle.provider as MockProvider; 8 | 9 | before(async () => { 10 | await provider.send('hardhat_reset', []); 11 | }); 12 | 13 | mockContractDirectTest(provider); 14 | mockContractProxiedTest(provider); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-hardhat/test/test-setup.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import {solidity} from 'ethereum-waffle'; 4 | 5 | chai.use(chaiAsPromised); 6 | chai.use(solidity); 7 | -------------------------------------------------------------------------------- /waffle-hardhat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-cli" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /waffle-mock-contract/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-mock-contract/.gitignore: -------------------------------------------------------------------------------- 1 | /**/dist 2 | cache 3 | src/Doppelganger.json 4 | test/helpers/interfaces 5 | -------------------------------------------------------------------------------- /waffle-mock-contract/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-mock-contract/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | compile.ts 4 | .eslintrc.js 5 | tsconfig.build.json 6 | tsconfig.json 7 | -------------------------------------------------------------------------------- /waffle-mock-contract/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/mock-contract 2 | 3 | ## 4.0.4 4 | 5 | ### Patch Changes 6 | 7 | - 4d83cde: Emit matcher improvement 8 | 9 | ## 4.0.3 10 | 11 | ### Patch Changes 12 | 13 | - da92375: Add mock contract deployment at a specified address 14 | - 46b954e: Add mock contract chaining behaviour 15 | - fb6863d: 🍶 Implement mocking receive function to revert 16 | - 1fa1312: Mock contract typing 17 | - a0f721a: Move ethers to peer deps 18 | 19 | ## 4.0.2 20 | 21 | ### Patch Changes 22 | 23 | - 00e9f1b: 🪵 Upgrade solc 24 | 25 | ## 4.0.1 26 | 27 | ### Patch Changes 28 | 29 | - e8adce7: 🧼 Add src folders to npm 30 | - be6fd8e: 🔝 Update ethers to 5.6.2 31 | - Exit prerelease 32 | 33 | ## 4.0.0-alpha.21 34 | 35 | ### Patch Changes 36 | 37 | - e8adce7: 🧼 Add src folders to npm 38 | 39 | ## 4.0.0-alpha.20 40 | 41 | ### Patch Changes 42 | 43 | - be6fd8e: 🔝 Update ethers to 5.6.2 44 | 45 | ## 4.0.0-alpha.1 46 | 47 | ### Patch Changes 48 | 49 | - 4c4b2d6: v4.0.0-alpha.1 50 | 51 | ## 4.0.0-alpha.0 52 | 53 | ### Major Changes 54 | 55 | - Bump typechain and ethers to the latest versions. Move them to peer deps. 56 | 57 | ## 3.3.1 58 | 59 | ### Patch Changes 60 | 61 | - 71417c7: Provider compatibility with London hardfork 62 | 63 | ## 3.3.0 64 | 65 | ### Minor Changes 66 | 67 | - 80d215b: - Fix vulnerabilities shown by `yarn audit` 68 | - Fix typings in `closeTo` matcher 69 | - Add `flattenSingleFile` function to compiler 70 | -------------------------------------------------------------------------------- /waffle-mock-contract/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-mock-contract/compile.ts: -------------------------------------------------------------------------------- 1 | import {compileAndSave} from '@ethereum-waffle/compiler'; 2 | 3 | const compile = async () => { 4 | console.log('Compiling mocking contract...'); 5 | await compileAndSave({ 6 | sourceDirectory: './src', 7 | outputDirectory: './src', 8 | compilerVersion: '0.6.3' 9 | }); 10 | }; 11 | 12 | compile(); 13 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/direct.test.ts: -------------------------------------------------------------------------------- 1 | import {MockProvider} from '@ethereum-waffle/provider'; 2 | import {mockContractDirectTest} from './directTest'; 3 | 4 | mockContractDirectTest(new MockProvider()); 5 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/buildTestContracts.ts: -------------------------------------------------------------------------------- 1 | import {compileAndSave} from '@ethereum-waffle/compiler'; 2 | 3 | const buildTestContracts = async () => { 4 | console.log('Building contracts...'); 5 | await compileAndSave({ 6 | sourceDirectory: './test/helpers/contracts', 7 | outputDirectory: './test/helpers/interfaces', 8 | compilerVersion: '0.6.3' 9 | }); 10 | }; 11 | 12 | void buildTestContracts(); 13 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/contracts/AmIRichAlready.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.3; 2 | 3 | interface IERC20 { 4 | function balanceOf(address account) external view returns (uint256); 5 | } 6 | 7 | contract AmIRichAlready { 8 | IERC20 private tokenContract; 9 | uint public richness = 1000000 * 10 ** 18; 10 | 11 | constructor (IERC20 _tokenContract) public { 12 | tokenContract = _tokenContract; 13 | } 14 | 15 | function check() public view returns (bool) { 16 | uint balance = tokenContract.balanceOf(msg.sender); 17 | return balance > richness; 18 | } 19 | 20 | function setRichness(uint256 _richness) public { 21 | richness = _richness; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.3; 2 | 3 | contract Counter { 4 | uint private value; 5 | 6 | function increment() public returns (uint) { 7 | value += 1; 8 | return value; 9 | } 10 | 11 | function increaseBy(uint a) public returns (uint) { 12 | require(a > 0, "A must be greater than 0"); 13 | 14 | value += a; 15 | return value; 16 | } 17 | 18 | function increaseByThreeValues(uint a, uint b, uint c) public { 19 | require(a > 0, "A must be greater than 0"); 20 | require(b > 0, "B must be greater than 0"); 21 | require(c > 0, "C must be greater than 0"); 22 | 23 | value += a; 24 | value += b; 25 | value += c; 26 | } 27 | 28 | function read() public view returns (uint) { 29 | return value; 30 | } 31 | 32 | function add(uint a) public view returns (uint) { 33 | return value + a; 34 | } 35 | 36 | function addThree(uint a, uint b, uint c) public view returns (uint) { 37 | require(a > 0, "A must be greater than 0"); 38 | require(b > 0, "B must be greater than 0"); 39 | require(c > 0, "C must be greater than 0"); 40 | 41 | return value + a + b + c; 42 | } 43 | 44 | function testArgumentTypes(uint a, bool b, string memory s, bytes memory bs) public pure returns (bytes memory ret) { 45 | ret = abi.encodePacked(a, b, s, bs); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/contracts/CounterOverloaded.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.3; 2 | 3 | contract CounterOverloaded { 4 | uint private value; 5 | 6 | function increment() public { 7 | value += 1; 8 | } 9 | 10 | function read() public view returns (uint) { 11 | return value; 12 | } 13 | 14 | function add() public view returns (uint) { 15 | return value + 1; 16 | } 17 | 18 | function add(uint a) public view returns (uint) { 19 | return value + a; 20 | } 21 | 22 | function testArgumentTypes(uint a, bool b, string memory s, bytes memory bs) public pure returns (bytes memory ret) { 23 | ret = abi.encodePacked(a, b, s, bs); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/contracts/EtherForward.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.3; 2 | 3 | interface IERC20 { 4 | function balanceOf(address account) external view returns (uint256); 5 | fallback() external payable; 6 | receive() external payable; 7 | } 8 | 9 | contract EtherForward { 10 | IERC20 private tokenContract; 11 | 12 | constructor (IERC20 _tokenContract) public { 13 | tokenContract = _tokenContract; 14 | } 15 | 16 | function forwardByCall() public payable { 17 | (bool sent, bytes memory data) = payable(tokenContract).call{value: msg.value}(""); 18 | if (!sent) { 19 | // https://ethereum.stackexchange.com/a/114140/24330 20 | // Bubble up the revert from the call. 21 | assembly { 22 | revert(add(data, 32), data) 23 | } 24 | } 25 | } 26 | 27 | function forwardBySend() public payable { 28 | require(payable(tokenContract).send(msg.value), "forwardBySend failed"); 29 | } 30 | 31 | function forwardByTransfer() public payable { 32 | payable(tokenContract).transfer(msg.value); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/helpers/contracts/Proxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.3; 2 | 3 | import "./Counter.sol"; 4 | 5 | contract Proxy { 6 | Counter private counter; 7 | 8 | constructor (Counter _counter) public { 9 | counter = _counter; 10 | } 11 | 12 | function incrementTwice() public returns (uint) { 13 | return counter.increment() + counter.increment(); 14 | } 15 | 16 | function increaseByTwice(uint a) public returns (uint) { 17 | return counter.increaseBy(a) + counter.increaseBy(a); 18 | } 19 | 20 | function cap(uint a) public pure returns (uint) { 21 | if (a > 10) { 22 | return 10; 23 | } 24 | return a; 25 | } 26 | 27 | function readCapped() public view returns (uint) { 28 | return cap(counter.read()); 29 | } 30 | 31 | function addCapped(uint a) public view returns (uint) { 32 | return cap(counter.add(a)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /waffle-mock-contract/test/proxied.test.ts: -------------------------------------------------------------------------------- 1 | import {mockContractProxiedTest} from './proxiedTest'; 2 | import {MockProvider} from '@ethereum-waffle/provider'; 3 | 4 | mockContractProxiedTest(new MockProvider()); 5 | -------------------------------------------------------------------------------- /waffle-mock-contract/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src", 5 | "src/**/*.json" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /waffle-mock-contract/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-compiler" 12 | }, 13 | { 14 | "path": "../waffle-provider" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /waffle-optimism/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-optimism/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.test.{js,ts}', 6 | file: 'test/test-setup.ts' 7 | } 8 | -------------------------------------------------------------------------------- /waffle-optimism/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @ethereum-waffle/optimism 2 | 3 | ## 4.0.3 4 | 5 | ### Patch Changes 6 | 7 | - a0f721a: Move ethers to peer deps 8 | 9 | ## 4.0.2 10 | 11 | ### Patch Changes 12 | 13 | - 9940630: 🦷 (Experimental) Automatically inject call history into hardhat provider 14 | 15 | ## 4.0.1 16 | 17 | ### Patch Changes 18 | 19 | - a26257e: Add build step for waffle-optimism 20 | - 761e076: Fix Optimism revertedWith matcher 21 | - e69f739: Support testing on optimism 22 | - Exit prerelease 23 | 24 | ## 4.0.0-alpha.22 25 | 26 | ### Patch Changes 27 | 28 | - 761e076: Fix Optimism revertedWith matcher 29 | 30 | ## 4.0.0-alpha.21 31 | 32 | ### Patch Changes 33 | 34 | - a26257e: Add build step for waffle-optimism 35 | - e69f739: Support testing on optimism 36 | -------------------------------------------------------------------------------- /waffle-optimism/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ethereum-waffle/optimism", 3 | "description": "Testing waffle with optimism", 4 | "version": "4.0.3", 5 | "author": "Marek Kirejczyk (http://ethworks.io)", 6 | "repository": "git@github.com:EthWorks/Waffle.git", 7 | "private": false, 8 | "license": "MIT", 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "main": "dist/cjs/src/index.js", 13 | "module": "dist/esm/src/index.ts", 14 | "types": "dist/esm/src/index.d.ts", 15 | "scripts": { 16 | "test": "true", 17 | "test:optimism": "mocha", 18 | "lint": "eslint '{src,test}/**/*.ts'", 19 | "lint:fix": "eslint --fix '{src,test}/**/*.ts'", 20 | "build": "rimraf ./dist && pnpm build:esm && pnpm build:cjs", 21 | "build:esm": "tsc -p tsconfig.build.json --outDir dist/esm --module ES6", 22 | "build:cjs": "tsc -p tsconfig.build.json --outDir dist/cjs" 23 | }, 24 | "engines": { 25 | "node": ">=10.0" 26 | }, 27 | "devDependencies": { 28 | "ethers": "5.6.2", 29 | "@ethereum-waffle/chai": "workspace:*", 30 | "@ethereum-waffle/provider": "workspace:*", 31 | "eslint": "^7.14.0", 32 | "ethereum-waffle": "workspace:*", 33 | "mocha": "^8.2.1", 34 | "rimraf": "^3.0.2", 35 | "typescript": "^4.6.2" 36 | }, 37 | "peerDependencies": { 38 | "ethers": "*" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /waffle-optimism/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './provider'; 2 | -------------------------------------------------------------------------------- /waffle-optimism/test/chaining.test.ts: -------------------------------------------------------------------------------- 1 | import {chainingMatchersTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | 4 | describe('Optimism: chaining', () => { 5 | const provider = new OptimismProvider(); 6 | 7 | chainingMatchersTest(provider); 8 | }); 9 | -------------------------------------------------------------------------------- /waffle-optimism/test/changeEtherBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {changeEtherBalanceTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | import {calculateL2TxGasFee} from './utils'; 4 | 5 | describe('Optimism: changeEtherBalance matcher', () => { 6 | const provider = new OptimismProvider(); 7 | let txGasFees: number; 8 | 9 | // needed to get fees for a single transaction on Optimism - it can be non constant 10 | before(async () => { 11 | txGasFees = await calculateL2TxGasFee(provider as any); 12 | }); 13 | 14 | changeEtherBalanceTest(provider, {txGasFees: () => txGasFees, baseFeePerGas: 1}); 15 | }); 16 | -------------------------------------------------------------------------------- /waffle-optimism/test/changeEtherBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {changeEtherBalancesTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | import {calculateL2TxGasFee} from './utils'; 4 | 5 | describe('Optimism: changeEtherBalances matcher', () => { 6 | const provider = new OptimismProvider(); 7 | let txGasFees: number; 8 | 9 | before(async () => { 10 | txGasFees = await calculateL2TxGasFee(provider as any); 11 | }); 12 | 13 | changeEtherBalancesTest(provider, {txGasFees: () => txGasFees, baseFeePerGas: 1}); 14 | }); 15 | -------------------------------------------------------------------------------- /waffle-optimism/test/changeTokenBalance.test.ts: -------------------------------------------------------------------------------- 1 | import {changeTokenBalanceTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | 4 | describe('Optimism: changeTokenBalance matcher', () => { 5 | const provider = new OptimismProvider(); 6 | 7 | changeTokenBalanceTest(provider); 8 | }); 9 | -------------------------------------------------------------------------------- /waffle-optimism/test/changeTokenBalances.test.ts: -------------------------------------------------------------------------------- 1 | import {changeTokenBalancesTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | 4 | describe('Optimism: changeEtherBalance matcher', () => { 5 | const provider = new OptimismProvider(); 6 | 7 | changeTokenBalancesTest(provider); 8 | }); 9 | -------------------------------------------------------------------------------- /waffle-optimism/test/events.test.ts: -------------------------------------------------------------------------------- 1 | import {eventsTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | 4 | describe('Optimism: changeEtherBalance matcher', () => { 5 | const provider = new OptimismProvider(); 6 | 7 | eventsTest(provider); 8 | }); 9 | -------------------------------------------------------------------------------- /waffle-optimism/test/reverted.test.ts: -------------------------------------------------------------------------------- 1 | import {revertedTest, revertedWithTest} from '@ethereum-waffle/chai/test'; 2 | import {OptimismProvider} from '../src/provider'; 3 | 4 | describe('Optimism: Matchers: reverted', () => { 5 | const provider = new OptimismProvider(); 6 | 7 | revertedTest(provider); 8 | }); 9 | 10 | describe('Optimism: Matchers: revertedWith', () => { 11 | const provider = new OptimismProvider(); 12 | 13 | revertedWithTest(provider, {includePanicCodes: false}); 14 | }); 15 | -------------------------------------------------------------------------------- /waffle-optimism/test/test-setup.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import {solidity} from 'ethereum-waffle'; 4 | 5 | chai.use(chaiAsPromised); 6 | chai.use(solidity); 7 | -------------------------------------------------------------------------------- /waffle-optimism/test/utils/getTxGasFees.ts: -------------------------------------------------------------------------------- 1 | import {OptimismProvider} from '../../src/provider'; 2 | 3 | /* needed to get fees for a single transaction on Optimism - it can be non constant 4 | * 5 | */ 6 | export const calculateL2TxGasFee = async (provider: OptimismProvider) => { 7 | const [sender, receiver] = provider.getWallets(); 8 | const tx = await sender.sendTransaction({ 9 | to: receiver.address, 10 | value: 200 11 | }); 12 | const txReceipt = await tx.wait(); 13 | const l1Fee = await provider.getL1Fee(txReceipt.transactionHash); 14 | const txGasFees = txReceipt.gasUsed.mul(tx.gasPrice ?? txReceipt.effectiveGasPrice).add(l1Fee).toNumber(); 15 | return txGasFees; 16 | }; 17 | -------------------------------------------------------------------------------- /waffle-optimism/test/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './getTxGasFees'; 2 | -------------------------------------------------------------------------------- /waffle-optimism/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-optimism/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-chai" 9 | }, 10 | { 11 | "path": "../waffle-cli" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /waffle-provider/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../.eslintrc.json') 2 | -------------------------------------------------------------------------------- /waffle-provider/.mocharc.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'test' 2 | module.exports = { 3 | require: 'ts-node/register/transpile-only', 4 | timeout: 50000, 5 | spec: 'test/**/*.{js,ts}' 6 | } 7 | -------------------------------------------------------------------------------- /waffle-provider/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | test 3 | .eslintrc.js 4 | tsconfig.build.json 5 | tsconfig.json 6 | -------------------------------------------------------------------------------- /waffle-provider/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ethworks sp z o.o. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /waffle-provider/patches/ganache+7.0.3.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/ganache/dist/ganache.d.ts b/node_modules/ganache/dist/ganache.d.ts 2 | index d5884c2..56b7392 100644 3 | --- a/node_modules/ganache/dist/ganache.d.ts 4 | +++ b/node_modules/ganache/dist/ganache.d.ts 5 | @@ -7061,7 +7061,7 @@ declare class EthereumProvider_2 extends Emittery<{ 6 | disconnect: () => Promise; 7 | } 8 | 9 | -declare type EthereumProviderOptions = Partial<{ 10 | +export declare type EthereumProviderOptions = Partial<{ 11 | [K in keyof EthereumConfig]: ExternalConfig; 12 | }>; 13 | 14 | -------------------------------------------------------------------------------- /waffle-provider/src/defaultAccounts.ts: -------------------------------------------------------------------------------- 1 | const balance = '0x1ED09BEAD87C0378D8E6400000000'; // 10^34 2 | 3 | const privateKeys = [ 4 | '0x29f3edee0ad3abf8e2699402e0e28cd6492c9be7eaab00d732a791c33552f797', 5 | '0x5c8b9227cd5065c7e3f6b73826b8b42e198c4497f6688e3085d5ab3a6d520e74', 6 | '0x50c8b3fc81e908501c8cd0a60911633acaca1a567d1be8e769c5ae7007b34b23', 7 | '0x706618637b8ca922f6290ce1ecd4c31247e9ab75cf0530a0ac95c0332173d7c5', 8 | '0xe217d63f0be63e8d127815c7f26531e649204ab9486b134ec1a0ae9b0fee6bcf', 9 | '0x8101cca52cd2a6d8def002ffa2c606f05e109716522ca2440b2cc84e4d49700b', 10 | '0x837fd366bc7402b65311de9940de0d6c0ba3125629b8509aebbfb057ebeaaa25', 11 | '0xba35c32f7cbda6a6cedeea5f73ff928d1e41557eddfd457123f6426a43adb1e4', 12 | '0x71f7818582e55456cb575eea3d0ce408dcf4cbbc3d845e86a7936d2f48f74035', 13 | '0x03c909455dcef4e1e981a21ffb14c1c51214906ce19e8e7541921b758221b5ae' 14 | ]; 15 | 16 | export const defaultAccounts = privateKeys 17 | .map(secretKey => ({balance, secretKey})); 18 | -------------------------------------------------------------------------------- /waffle-provider/src/fixtures.ts: -------------------------------------------------------------------------------- 1 | import {providers, Wallet} from 'ethers'; 2 | import {MockProvider} from './MockProvider'; 3 | 4 | export type Fixture = (wallets: Wallet[], provider: MockProvider) => Promise; 5 | interface Snapshot { 6 | fixture: Fixture; 7 | data: T; 8 | id: string; 9 | provider: providers.Web3Provider; 10 | wallets: Wallet[]; 11 | } 12 | 13 | export const loadFixture = createFixtureLoader(); 14 | 15 | export function createFixtureLoader(overrideWallets?: Wallet[], overrideProvider?: MockProvider) { 16 | const snapshots: Snapshot[] = []; 17 | 18 | return async function load(fixture: Fixture): Promise { 19 | const snapshot = snapshots.find((snapshot) => snapshot.fixture === fixture); 20 | if (snapshot) { 21 | await snapshot.provider.send('evm_revert', [snapshot.id]); 22 | snapshot.id = await snapshot.provider.send('evm_snapshot', []); 23 | return snapshot.data; 24 | } else { 25 | const provider = overrideProvider ?? new MockProvider(); 26 | const wallets = overrideWallets ?? provider.getWallets(); 27 | 28 | const data = await fixture(wallets, provider); 29 | const id = await provider.send('evm_snapshot', []); 30 | 31 | snapshots.push({fixture, data, id, provider, wallets}); 32 | return data; 33 | } 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /waffle-provider/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MockProvider'; 2 | export * from './fixtures'; 3 | export * from './defaultAccounts'; 4 | export * from './revertString'; 5 | export * from './test-provider'; 6 | -------------------------------------------------------------------------------- /waffle-provider/src/log.ts: -------------------------------------------------------------------------------- 1 | import debug from 'debug'; 2 | 3 | const log = debug('waffle:waffle-provider'); 4 | 5 | export {log}; 6 | -------------------------------------------------------------------------------- /waffle-provider/src/test-provider.ts: -------------------------------------------------------------------------------- 1 | import type {BigNumber, providers, Wallet} from 'ethers'; 2 | 3 | export type TestProvider = 4 | providers.BaseProvider 5 | & { 6 | getWallets(): Wallet[]; 7 | getL1Fee?(txHash: string): Promise; 8 | }; 9 | -------------------------------------------------------------------------------- /waffle-provider/test/Caller.ts: -------------------------------------------------------------------------------- 1 | export const SOURCE = ` 2 | pragma solidity ^0.6.0; 3 | 4 | contract Called { 5 | function foo (uint a, uint b) external { 6 | } 7 | } 8 | 9 | contract Caller { 10 | function callOther (Called a) external { 11 | a.foo(1, 2); 12 | } 13 | } 14 | `; 15 | 16 | export const CALLED_ABI = [ 17 | 'function foo(uint a, uint b) public' 18 | ]; 19 | 20 | // eslint-disable-next-line max-len 21 | export const CALLED_BYTECODE = '6080604052348015600f57600080fd5b5060898061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806304bc52f814602d575b600080fd5b604d60048036036040811015604157600080fd5b5080359060200135604f565b005b505056fea2646970667358221220bac459444897f57b4c66996221a763780e8ba7d431f77f25041e5787e21922ad64736f6c63430006010033'; 22 | 23 | export const CALLER_ABI = [ 24 | 'function callOther(address a) public' 25 | ]; 26 | 27 | // eslint-disable-next-line max-len 28 | export const CALLER_BYTECODE = '608060405234801561001057600080fd5b5060ef8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806338e6876a14602d575b600080fd5b605060048036036020811015604157600080fd5b50356001600160a01b03166052565b005b6040805162978a5f60e31b8152600160048201526002602482015290516001600160a01b038316916304bc52f891604480830192600092919082900301818387803b158015609f57600080fd5b505af115801560b2573d6000803e3d6000fd5b505050505056fea2646970667358221220ea1dc566804cc21bb6ecff7aba87f2f6d2f89bd28ddaad6f99012860617f049564736f6c63430006010033'; 29 | -------------------------------------------------------------------------------- /waffle-provider/test/MockProviderCases.ts: -------------------------------------------------------------------------------- 1 | import {MockProvider} from '../src'; 2 | import {TestProvider} from '../src/test-provider'; 3 | 4 | export const describeMockProviderCases = ( 5 | title: string, 6 | testCases: (provider: TestProvider) => void 7 | ) => { 8 | describe(title, () => { 9 | describe('default options', () => { 10 | const provider = new MockProvider(); 11 | testCases(provider); 12 | }); 13 | 14 | describe('instanbul hardfork', () => { 15 | const provider = new MockProvider({ 16 | ganacheOptions: { 17 | chain: { 18 | hardfork: 'istanbul' 19 | } 20 | } 21 | }); 22 | testCases(provider); 23 | }); 24 | 25 | describe('berlin hardfork', () => { 26 | const provider = new MockProvider({ 27 | ganacheOptions: { 28 | chain: { 29 | hardfork: 'berlin' 30 | } 31 | } 32 | }); 33 | testCases(provider); 34 | }); 35 | 36 | describe('london hardfork', () => { 37 | const provider = new MockProvider({ 38 | ganacheOptions: { 39 | chain: { 40 | hardfork: 'london' 41 | } 42 | } 43 | }); 44 | testCases(provider); 45 | }); 46 | 47 | describe('with block gas limit', () => { 48 | const provider = new MockProvider({ 49 | ganacheOptions: { 50 | miner: { 51 | blockGasLimit: 9_999_999 52 | } 53 | } 54 | }); 55 | testCases(provider); 56 | }); 57 | }); 58 | }; 59 | -------------------------------------------------------------------------------- /waffle-provider/test/index.ts: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | 4 | chai.use(chaiAsPromised); 5 | -------------------------------------------------------------------------------- /waffle-provider/test/revertString.test.ts: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai'; 2 | import {constants} from 'ethers'; 3 | import {appendRevertString} from '../src/revertString'; 4 | import {deployToken} from './BasicToken'; 5 | import {describeMockProviderCases} from './MockProviderCases'; 6 | 7 | describeMockProviderCases('INTEGRATION: MockProvider.callHistory', (provider) => { 8 | it('decodes revert strings from calls', async () => { 9 | const [wallet] = provider.getWallets(); 10 | 11 | const token = await deployToken(wallet, 10); 12 | 13 | try { 14 | await token.transfer(constants.AddressZero, 1); 15 | } catch (transactionError: any) { 16 | await appendRevertString(provider, transactionError.receipt); 17 | expect(transactionError.receipt.revertString).to.be.equal('Invalid address'); 18 | } 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /waffle-provider/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /waffle-provider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist" 5 | }, 6 | "references": [ 7 | { 8 | "path": "../waffle-ens" 9 | } 10 | ] 11 | } 12 | --------------------------------------------------------------------------------