From 02fde4c7615f9dd424fe33e6cb9019aa116f8d3f Mon Sep 17 00:00:00 2001 From: myelinated-wackerow <263208946+myelinated-wackerow@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:59:35 +0000 Subject: [PATCH 1/2] deprecation: remove Waffle tutorials Ethereum Waffle is effectively unmaintained (last release ~3 years ago) and has been superseded by Hardhat Chai Matchers and Foundry. Remove all four Waffle tutorials and their translations across 13 languages to avoid directing developers to a dead-end toolchain. Removed tutorials: - testing-erc-20-tokens-with-waffle - waffle-dynamic-mocking-and-testing-calls - waffle-say-hello-world-with-hardhat-and-ethers - waffle-test-simple-smart-contract Co-Authored-By: Claude Opus 4.6 Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com> --- .../index.md | 1147 ----------------- .../index.md | 293 ----- .../test-one.png | Bin 39200 -> 0 bytes .../test-three.png | Bin 72321 -> 0 bytes .../test-two.png | Bin 52950 -> 0 bytes .../index.md | 197 --- .../index.md | 199 --- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 205 --- .../index.md | 1146 ---------------- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 205 --- .../index.md | 1147 ----------------- .../index.md | 298 ----- .../index.md | 202 --- .../index.md | 199 --- .../index.md | 1145 ---------------- .../index.md | 298 ----- .../index.md | 202 --- .../index.md | 1145 ---------------- .../index.md | 298 ----- .../index.md | 202 --- .../index.md | 199 --- .../index.md | 1145 ---------------- .../index.md | 293 ----- .../index.md | 204 --- .../index.md | 199 --- .../index.md | 297 ----- .../index.md | 1145 ---------------- .../index.md | 298 ----- .../index.md | 202 --- .../index.md | 199 --- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 199 --- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 205 --- .../index.md | 1145 ---------------- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 132 -- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 205 --- .../index.md | 300 ----- .../index.md | 204 --- .../index.md | 199 --- .../index.md | 293 ----- .../index.md | 204 --- .../index.md | 199 --- .../index.md | 1145 ---------------- .../index.md | 293 ----- .../index.md | 204 --- .../index.md | 199 --- src/data/internalTutorials.json | 1 - ...ynamic-mocking-and-testing-calls-data.json | 14 - 59 files changed, 20874 deletions(-) delete mode 100644 public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png delete mode 100644 public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-three.png delete mode 100644 public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png delete mode 100644 public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/pl/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/pt-br/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/pt-br/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/pt-br/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/pt-br/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/sw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/sw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/sw/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/te/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/te/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/te/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/tr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/tr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/tr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/tr/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/uk/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/uk/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/uk/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/ur/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/ur/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/ur/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/zh-tw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/zh-tw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/zh-tw/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 public/content/translations/zh/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md delete mode 100644 public/content/translations/zh/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md delete mode 100644 public/content/translations/zh/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md delete mode 100644 public/content/translations/zh/developers/tutorials/waffle-test-simple-smart-contract/index.md delete mode 100644 src/data/placeholders/content-developers-tutorials-waffle-dynamic-mocking-and-testing-calls-data.json diff --git a/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 00a9ba4938c..00000000000 --- a/public/content/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1147 +0,0 @@ ---- -title: Testing ERC-20 tokens with Waffle -description: Learn how test Solidity smart contracts and use smart contract matchers with Waffle. -author: Vladislav Starostenko -tags: ["waffle", "smart contracts", "solidity", "testing", "erc-20"] -skill: intermediate -lang: en -published: 2020-10-16 ---- - -In this tutorial you will learn how to: - -- Write tests for smart contracts with Waffle -- Use some popular matchers to test smart contracts with Waffle - -Assumptions: - -- you can get around in a terminal, -- you can create a new `JavaScript` project, -- you've written a few lines of `Solidity` code, -- you've written a few tests in `JavaScript`, -- you’ve used `yarn` or `npm`, JavaScripts’s package installer. - -Again, if any of these are untrue, or you don’t plan to reproduce the code in this article, you can likely still follow along just fine. - -## A few words about Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) is the most advanced library for writing and testing smart contracts. - -Works with the [JavaScript API](/developers/docs/apis/javascript/) ethers-js. - -You can read more details in the [Waffle documentation](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation) ! - -## The quick tutorial {#the-quick-tutorial} - -First things first, create new `JavaScript` or `TypeScript` project ( I'll use `TS`, but if you use `JS` it's not a problem ) : - -Somewhat like this : - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Step #1: Install waffle in your project [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -To get started, install `ethereum-waffle`. In this tutorial, I'll use `yarn`, so to install `ethereum-waffle` run: - -```bash - yarn add --dev ethereum-waffle -``` - -## Step #2: Write a smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -In this tutorial, I'll use [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) token from [OpenZeppelin](https://openzeppelin.com). - -So, add `OpenZeppelin` by installing it with `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Then create `BasicToken.sol` contract in `src` directory: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class derived from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Step #3: Compile your smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -To compile your smart contract add the following entry in the `package.json` of your project : - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Also, add `waffle.json` file in the main directory of your project. - -An example of `waffle.json` configuration: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -You can read more about the Waffle configuration [here](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Then just run `yarn build` to compile your smart contract. - -You should see that Waffle compiled your contract and placed the resulting JSON output inside the `build` directory. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;142:152:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2219:81:2;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;2219:81:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4255:166;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4255:166:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3262:98;;;:::i;:::-;;;;;;;;;;;;;;;;;;;4881:317;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;4881:317:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3121:81;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;5593:215;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;5593:215:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3418:117;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3418:117:2;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2413:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;2413:85:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6295:266;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6295:266:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3738:172;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3738:172:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;3968:149;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3968:149:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;2219:81;2256:13;2288:5;2281:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2219:81;:::o;4255:166::-;4338:4;4354:39;4363:12;:10;:12::i;:::-;4377:7;4386:6;4354:8;:39::i;:::-;4410:4;4403:11;;4255:166;;;;:::o;3262:98::-;3315:7;3341:12;;3334:19;;3262:98;:::o;4881:317::-;4987:4;5003:36;5013:6;5021:9;5032:6;5003:9;:36::i;:::-;5049:121;5058:6;5066:12;:10;:12::i;:::-;5080:89;5118:6;5080:89;;;;;;;;;;;;;;;;;:11;:19;5092:6;5080:19;;;;;;;;;;;;;;;:33;5100:12;:10;:12::i;:::-;5080:33;;;;;;;;;;;;;;;;:37;;:89;;;;;:::i;:::-;5049:8;:121::i;:::-;5187:4;5180:11;;4881:317;;;;;:::o;3121:81::-;3162:5;3186:9;;;;;;;;;;;3179:16;;3121:81;:::o;5593:215::-;5681:4;5697:83;5706:12;:10;:12::i;:::-;5720:7;5729:50;5768:10;5729:11;:25;5741:12;:10;:12::i;:::-;5729:25;;;;;;;;;;;;;;;:34;5755:7;5729:34;;;;;;;;;;;;;;;;:38;;:50;;;;:::i;:::-;5697:8;:83::i;:::-;5797:4;5790:11;;5593:215;;;;:::o;3418:117::-;3484:7;3510:9;:18;3520:7;3510:18;;;;;;;;;;;;;;;;3503:25;;3418:117;;;:::o;2413:85::-;2452:13;2484:7;2477:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2413:85;:::o;6295:266::-;6388:4;6404:129;6413:12;:10;:12::i;:::-;6427:7;6436:96;6475:15;6436:96;;;;;;;;;;;;;;;;;:11;:25;6448:12;:10;:12::i;:::-;6436:25;;;;;;;;;;;;;;;:34;6462:7;6436:34;;;;;;;;;;;;;;;;:38;;:96;;;;;:::i;:::-;6404:8;:129::i;:::-;6550:4;6543:11;;6295:266;;;;:::o;3738:172::-;3824:4;3840:42;3850:12;:10;:12::i;:::-;3864:9;3875:6;3840:9;:42::i;:::-;3899:4;3892:11;;3738:172;;;;:::o;3968:149::-;4057:7;4083:11;:18;4095:5;4083:18;;;;;;;;;;;;;;;:27;4102:7;4083:27;;;;;;;;;;;;;;;;4076:34;;3968:149;;;;:::o;590:104:0:-;643:15;677:10;670:17;;590:104;:::o;9357:340:2:-;9475:1;9458:19;;:5;:19;;;;9450:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9555:1;9536:21;;:7;:21;;;;9528:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9637:6;9607:11;:18;9619:5;9607:18;;;;;;;;;;;;;;;:27;9626:7;9607:27;;;;;;;;;;;;;;;:36;;;;9674:7;9658:32;;9667:5;9658:32;;;9683:6;9658:32;;;;;;;;;;;;;;;;;;9357:340;;;:::o;7035:530::-;7158:1;7140:20;;:6;:20;;;;7132:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7241:1;7220:23;;:9;:23;;;;7212:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7294:47;7315:6;7323:9;7334:6;7294:20;:47::i;:::-;7372:71;7394:6;7372:71;;;;;;;;;;;;;;;;;:9;:17;7382:6;7372:17;;;;;;;;;;;;;;;;:21;;:71;;;;;:::i;:::-;7352:9;:17;7362:6;7352:17;;;;;;;;;;;;;;;:91;;;;7476:32;7501:6;7476:9;:20;7486:9;7476:20;;;;;;;;;;;;;;;;:24;;:32;;;;:::i;:::-;7453:9;:20;7463:9;7453:20;;;;;;;;;;;;;;;:55;;;;7540:9;7523:35;;7532:6;7523:35;;;7551:6;7523:35;;;;;;;;;;;;;;;;;;7035:530;;;:::o;1746:187:1:-;1832:7;1864:1;1859;:6;;1867:12;1851:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;1851:29:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1890:9;1906:1;1902;:5;1890:17;;1925:1;1918:8;;;1746:187;;;;;:::o;874:176::-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;10695:92:2:-;;;;:::o" - } - }, - "bytecode": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033" - } -``` - -
- -## Step #4: Test your smart contract [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Step #4.1 Install necessary dependencies [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -After we have successfully authored a Smart Contract we can test it. We will use `Waffle` to do it. - -Tests in `Waffle` are written using `Mocha` alongside with `Chai`. We can use a different test environment, but `Waffle` matchers only work with `Chai`. - -So, we need to add `Chai` to our dependencies : - -```bash - yarn add --dev mocha chai -``` - -### Step #4.2 Create test file [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -To write our test we need to create `BasicToken.test.ts` file in our test directory. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -So, we use `deployContract` method from `Waffle` to deploy our token. As arguments, we should pass `wallet`, the compiled json file of our contract and default balance. - -`Waffle` also allows us to create a `wallet`, which makes it very easy to deploy a contract. - -You can read more about `wallet` [here](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) and you can read more about the deploying function [here](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Let's write a simple test to check balance of our wallet. Since we submitted the value 1000 during the deployment our contract, the balance of our wallet must be 1000 tokens, which we can check in the first test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -To run the test use `yarn test` - -### Step #4.3 Emitting events [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -In this tutorial, I want to show you the most useful matchers of `Waffle`, so let's start with the first one. - -`Waffle` allows us to test what events where emitted. - -In this tutorial, I'll test the `transfer` method of our contract. - -In this test, I'll make a transfer from one wallet to another and check whether the `Transfer` event was called. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Also, a big advantage of this matcher is that we can check which arguments this event was called with by adding `withArgs` to our test. - -This will allow us to be sure that our function is being called correctly! - -### Step #4.4 Revert with message [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` allows us to test what message it was reverted with. - -We will use `revertedWith` matcher in our test to check it. - -We can write a test in which we will perform a transfer for an amount greater than we have on our wallet. -And then we'll check if the transaction reverted with the exact message! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Step #4.5 Change-token-balance [Link to doc](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` allows us to check for changes in the balances of the wallets! - -We can use the `changeTokenBalance` matcher to check the balance change or the `changeTokenBalances` for a multiple account. - -The matcher can accept `numbers`, `strings` and `BigNumbers` as a balance change, while the address should be specified as a wallet or a contract. - -Let's write the next test: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -The above is a test for a single wallet. - -And the next one for multiple wallets: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -The transaction is expected to be passed as a callback (we need to check the balance before the call) or as a transaction response. - -## Congratulations {#congratulations} - -**Congratulations! You've made it through my tutorial. You've taken your first big step towards testing smart contracts with Waffle.** - -**Code from this tutorial you can be find [here](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**More documentation about `Waffle` available [here](https://getwaffle.io).** diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index d7b3901c96c..00000000000 --- a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle: Dynamic mocking and testing contract calls" -description: Advanced Waffle tutorial for using dynamic mocking and testing contract calls -author: "Daniel Izdebski" -tags: ["waffle", "smart contracts", "solidity", "testing", "mocking"] -skill: intermediate -lang: en -published: 2020-11-14 ---- - -## What is this tutorial about? {#what-is-this-tutorial-about} - -In this tutorial you will learn how to: - -- use dynamic mocking -- test interactions between smart contracts - -Assumptions: - -- you already know how to write a simple smart contract in `Solidity` -- you know your way around `JavaScript` and `TypeScript` -- you've done other `Waffle` tutorials or know a thing or two about it - -## Dynamic mocking {#dynamic-mocking} - -Why is dynamic mocking useful? Well, it allows us to write unit tests instead of integration tests. What does it mean? It means that we don't have to worry about smart contracts' dependencies, thus we can test all of them in complete isolation. Let me show you how exactly you can do it. - -### **1. Project** {#1-project} - -Before we start we need to prepare a simple node.js project: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Let's start with adding typescript and test dependencies - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Now let's add `Waffle` and `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -Your project structure should look like this now: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Smart contract** {#2-smart-contract} - -To start dynamic mocking, we need a smart contract with dependencies. Don't worry, I've got you covered! - -Here's a simple smart contract written in `Solidity` whose sole purpose is to check if we're rich. It uses ERC20 token to check if we have enough tokens. Put it in `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -As we want to use dynamic mocking we don't need the whole ERC20, that's why we're using the IERC20 interface with only one function. - -It's time to build this contract! For that we will use `Waffle`. First, we're going to create a simple `waffle.json` config file which specifies compilation options. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Now we're ready to build the contract with Waffle: - -```bash -npx waffle -``` - -Easy, right? In `build/` folder two files corresponding to the contract and the interface appeared. We will use them later for testing. - -### **3. Testing** {#3-testing} - -Let's create a file called `AmIRichAlready.test.ts` for the actual testing. First of all, we have to handle the imports. We will need them for later: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Except for JS dependencies, we need to import our built contract and interface: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle uses `chai` for testing. However, before we can use it, we have to inject Waffle's matchers into chai itself: - -```typescript -use(solidity) -``` - -We need to implement `beforeEach()` function that will reset the state of the contract before each test. Let's first think of what we need there. To deploy a contract we need two things: a wallet and a deployed ERC20 contract to pass it as an argument for the `AmIRichAlready` contract. - -Firstly we create a wallet: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Then we need to deploy an ERC20 contract. Here's the tricky part - we have only an interface. This is the part where Waffle comes to save us. Waffle has a magical `deployMockContract()` function that creates a contract using solely the _abi_ of the interface: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Now with both the wallet and the deployed ERC20, we can go ahead and deploy the `AmIRichAlready` contract: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -With all of that, our `beforeEach()` function is finished. So far your `AmIRichAlready.test.ts` file should look like this: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Let's write the first test for the `AmIRichAlready` contract. What do you think our test should be about? Yeah, you're right! We should check if we are already rich :) - -But wait a second. How will our mocked contract know what values to return? We haven't implemented any logic for the `balanceOf()` function. Again, Waffle can help here. Our mocked contract has some new fancy stuff to it now: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -With this knowledge we can finally write our first test: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Let's break down this test into parts: - -1. We set our mock ERC20 contract to always return balance of 999999 tokens. -2. Check if the `contract.check()` method returns `false`. - -We're ready to fire up the beast: - -![One test passing](./test-one.png) - -So the test works, but... there's still some room for improvement. The `balanceOf()` function will always return 99999. We can improve it by specifying a wallet for which the function should return something - just like a real contract: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -So far, we've tested only the case where we're not rich enough. Let's test the opposite instead: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -You run the tests... - -![Two tests passing](test-two.png) - -...and here you are! Our contract seems to work as intended :) - -## Testing contract calls {#testing-contract-calls} - -Let's sum up what've done so far. We've tested the functionality of our `AmIRichAlready` contract and it seems to be working properly. That means we're done, right? Not exactly! Waffle allows us to test our contract even further. But how exactly? Well, in Waffle's arsenal there's a `calledOnContract()` and `calledOnContractWith()` matchers. They will allow us to check if our contract called the ERC20 mock contract. Here's a basic test with one of these matchers: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -We can go even further and improve this test with the other matcher I told you about: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Let's check if the tests are correct: - -![Three tests passing](test-three.png) - -Great, all tests are green. - -Testing contract calls with Waffle is super easy. And here's the best part. These matchers work with both normal and mocked contracts! It is because Waffle records and filters EVM calls rather than inject code, like it is the case of popular testing libraries for other technologies. - -## The Finish Line {#the-finish-line} - -Congrats! Now you know how to use Waffle to test contract calls and mock contracts dynamically. There are far more interesting features to discover. I recommend diving into Waffle's documentation. - -Waffle's documentation is available [here](https://ethereum-waffle.readthedocs.io/). - -Source code for this tutorial can be found [here](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutorials you may also be interested in: - -- [Testing smart contracts with Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png deleted file mode 100644 index ce773780c2526a712286b69d717e2647a1c956ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39200 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 z 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 Hd;EU@LdVLQ diff --git a/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png b/public/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png deleted file mode 100644 index 2477c32bd91800b454760018ccc830558ae1287c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52950 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 diff --git a/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 306f32dc93c..00000000000 --- a/public/content/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: "Waffle say hello world tutorial with hardhat and ethers" -description: Make your first Waffle project with hardhat and ethers.js -author: "MiZiet" -tags: - ["waffle", "smart contracts", "solidity", "testing", "hardhat", "ethers.js"] -skill: beginner -lang: en -published: 2020-10-16 ---- - -In this [Waffle](https://ethereum-waffle.readthedocs.io) tutorial, we will learn how to set up a simple "Hello world" smart contract project, using [hardhat](https://hardhat.org/) and [ethers.js](https://docs.ethers.io/v5/). Then we will learn how to add a new functionality to our smart contract and how to test it with Waffle. - -Let's start by creating a new project: - -```bash -yarn init -``` - -or - -```bash -npm init -``` - -and installing required packages: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -or - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Next step is creating a sample hardhat project by running `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Select `Create a sample project` - -Our project's structure should look like this: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Now let's talk about some of these files: {#now-lets-talk} - -- Greeter.sol - our smart contract written in solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Our smart contract can be divided into three parts: - -1. constructor - where we declare a string type variable called `greeting`, -2. function greet - a function that will return the `greeting` when called, -3. function setGreeting - a function that allows us to change the `greeting` value. - -- sample-test.js - our tests file - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Next step consists of compiling our contract and running tests: {#compiling-and-testing} - -Waffle tests use Mocha (a test framework) with Chai (an assertion library). All you have to do is run `npx hardhat test` and wait for the following message to appear. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Everything looks great so far, let's add some more complexity to our project {#adding-complexity} - -Imagine a situation where someone adds an empty string as a greeting. It wouldn't be a warm greeting, right? -Let's make sure that doesn't happen: - -We want to use solidity's `revert` when someone passes an empty string. A good thing is that we can easily test this functionality with Waffle's chai matcher `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Looks like our new test didn't pass: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Let's implement this functionality into our smart contract: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Now, our setGreeting function looks like this: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Let's run tests again: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Congrats! You made it :) - -### Conclusion {#conclusion} - -We made a simple project with Waffle, Hardhat and ethers.js. We learned how to set up a project, add a test and implement new functionality. - -For more great chai matchers to test your smart contracts, check [official Waffle's docs](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 42665429206..00000000000 --- a/public/content/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Testing simple smart contract with Waffle library -description: Tutorial for beginners -author: Ewa Kowalska -tags: ["smart contracts", "solidity", "Waffle", "testing"] -skill: beginner -lang: en -published: 2021-02-26 ---- - -## In this tutorial you'll learn how to {#in-this-tutorial-youll-learn-how-to} - -- Test the changes of wallet balance -- Test emission of events with specified arguments -- Assert that a transaction was reverted - -## Assumptions {#assumptions} - -- You can create a new JavaScript or TypeScript project -- You have some basic experience with tests in JavaScript -- You have used some package managers like yarn or npm -- You possess very basic knowledge of smart contracts and Solidity - -## Getting started {#getting-started} - -The tutorial demonstrates test setup and run using yarn, but there is no problem if you prefer npm - I will provide proper references to the official Waffle [documentation](https://ethereum-waffle.readthedocs.io/en/latest/index.html). - -## Install Dependencies {#install-dependencies} - -[Add](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) ethereum-waffle and typescript dependencies to the dev dependencies of your project. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Example smart contract {#example-smart-contract} - -During the tutorial we'll work on a simple smart contract example - EtherSplitter. It does not much apart from allowing anyone to send some wei and split it evenly between two predefined receivers. -The split function requires the number of wei to be even, otherwise it will revert. For both receivers it performs a wei transfer followed by emission of the Transfer event. - -Place the snippet of EtherSplitter code in `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Compile the contract {#compile-the-contract} - -To [compile](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) the contract add the following entry to the package.json file: - -```json -"scripts": { - "build": "waffle" - } -``` - -Next, create the Waffle configuration file in the project root directory - `waffle.json` - and then paste the following configuration there: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Run `yarn build`. As the result, the `build` directory will appear with the EtherSplitter compiled contract in JSON format. - -## Test setup {#test-setup} - -Testing with Waffle requires using Chai matchers and Mocha, so you need to [add](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) them to your project. Update your package.json file and add the `test` entry in the scripts part: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -If you want to [execute](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) your tests, just run `yarn test` . - -## Testing {#testing} - -Now create the `test` directory and create the new file `test\EtherSplitter.test.ts`. -Copy the snippet below and paste it to our test file. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -A few words before we start. -The `MockProvider` comes up with a mock version of the blockchain. It also delivers mock wallets that will serve us for testing EtherSplitter contract. We can get up to ten wallets by calling `getWallets()` method on the provider. In the example, we get three wallets - for the sender and for two receivers. - -Next, we declare a variable called 'splitter' - this is our mock EtherSplitter contract. It is created before each execution of a single test by the `deployContract` method. This method simulates deployment of a contract from the wallet passed as the first parameter (sender's wallet in our case). The second parameter is the ABI and the bytecode of the tested contract - we pass there the json file of the compiled EtherSplitter contract from the `build` directory. The third parameter is an array with the contract's constructor arguments, which in our case, are the two addresses of the receivers. - -## changeBalances {#changebalances} - -First, we will check if the split method actually changes the balances of receivers' wallets. If we split 50 wei from senders account, we would expect the balances of both receivers to increase by 25 wei. We will use Waffle's `changeBalances` matcher: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -As the first parameter of the matcher, we pass an array of receivers' wallets, and as the second - an array of expected increases on corresponding accounts. -If we wanted to check the balance of one specific wallet, we could also use `changeBalance` matcher, which does not require passing arrays, as in the example below: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Note that in both cases of `changeBalance` and `changeBalances` we pass the split function as a callback because the matcher needs to access the state of balances before and after the call. - -Next, we'll test if the Transfer event was emitted after each transfer of wei. We'll turn to another matcher from Waffle: - -## Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -The `emit` matcher allows us to check if a contract emitted an event on calling a method. As the parameters to the `emit` matcher, we provide the mock contract that we predict to emit the event, along with the name of that event. In our case, the mock contract is `splitter` and the name of the event - `Transfer`. We can also verify the precise values of arguments that the event was emitted with - we pass as many arguments to `withArgs` matcher, as our event declaration expects. In case of EtherSplitter contract, we pass the addresses of the sender and the receiver along with the transferred wei amount. - -## revertedWith {#revertedwith} - -As the last example, we'll check if the transaction was reverted in case of uneven number of wei. We'll use `revertedWith` matcher: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -The test, if passed, will assure us that the transaction was reverted indeed. However, there must be also an exact match between the messages that we passed in `require` statement and the message we expect in `revertedWith`. If we go back to the code of EtherSplitter contract, in the `require` statement for the wei amount, we provide the message: 'Uneven wei amount not allowed'. This matches the message we expect in our test. If they were not equal, the test would fail. - -## Congratulations! {#congratulations} - -You've made your first big step towards testing smart contracts with Waffle! diff --git a/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 406a3bbaecc..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: Dynamické mockování a testování volání kontraktů" -description: "Pokročilý tutoriál pro Waffle o použití dynamického mockování a testování volání kontraktů" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "smart kontrakt účty", - "solidity", - "testování", - "mocking" - ] -skill: intermediate -lang: cs -published: 2020-11-14 ---- - -## O čem je tento tutoriál? {#what-is-this-tutorial-about} - -V tomto tutoriálu se dozvíte, jak: - -- používat dynamické mockování -- testovat interakce mezi chytrými kontrakty - -Předpoklady: - -- už umíte napsat jednoduchý chytrý kontrakt v `Solidity` -- orientujete se v `JavaScriptu` a `TypeScriptu` -- už jste absolvovali jiné tutoriály o `Waffle` nebo o něm už něco málo víte - -## Dynamické mockování {#dynamic-mocking} - -Proč je dynamické mockování užitečné? Umožňuje nám psát unit testy namísto integračních testů. Co to znamená? Znamená to, že se nemusíme starat o závislosti chytrých kontraktů, a tak je můžeme všechny testovat v naprosté izolaci. Dovolte mi, abych vám přesně ukázal, jak to můžete udělat. - -### **1.** Projekt\*\* {#1-project} - -Než začneme, musíme si připravit jednoduchý projekt node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# nebo pokud používáte npm -npm init -``` - -Začněme přidáním závislostí pro typescript a testování - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# nebo pokud používáte npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Nyní přidejme `Waffle` a `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# nebo pokud používáte npm -npm install ethereum-waffle ethers --save-dev -``` - -Struktura vašeho projektu by nyní měla vypadat takto: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2.** Chytrý kontrakt\*\* {#2-smart-contract} - -Abychom mohli začít s dynamickým mockováním, potřebujeme chytrý kontrakt se závislostmi. Nebojte se, mám to pro vás připravené! - -Zde je jednoduchý chytrý kontrakt napsaný v `Solidity`, jehož jediným účelem je zkontrolovat, zda jsme bohatí. Používá token ERC20 ke kontrole, zda máme dostatek tokenů. Vložte ho do `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Jelikož chceme použít dynamické mockování, nepotřebujeme celý ERC20, proto používáme rozhraní IERC20 s jedinou funkcí. - -Je čas tento kontrakt sestavit! K tomu použijeme `Waffle`. Nejprve vytvoříme jednoduchý konfigurační soubor `waffle.json`, který specifikuje možnosti kompilace. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Nyní jsme připraveni sestavit kontrakt s Waffle: - -```bash -npx waffle -``` - -Snadné, že? Ve složce `build/` se objevily dva soubory odpovídající kontraktu a rozhraní. Použijeme je později pro testování. - -### **3.** Testování\*\* {#3-testing} - -Vytvořme si soubor s názvem `AmIRichAlready.test.ts` pro samotné testování. Nejprve se musíme postarat o importy. Budeme je potřebovat později: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Kromě závislostí JS musíme importovat náš sestavený kontrakt a rozhraní: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle používá pro testování `chai`. Než ho však budeme moci použít, musíme do samotného chai vložit matchery od Waffle: - -```typescript -use(solidity) -``` - -Musíme implementovat funkci `beforeEach()`, která obnoví stav kontraktu před každým testem. Nejdřív si rozmysleme, co tam budeme potřebovat. K nasazení kontraktu potřebujeme dvě věci: peněženku a nasazený kontrakt ERC20, který předáme jako argument kontraktu `AmIRichAlready`. - -Nejprve si vytvoříme peněženku: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Poté musíme nasadit kontrakt ERC20. Tady je ta záludná část – máme pouze rozhraní. Tohle je ta část, kde nás Waffle přichází zachránit. Waffle má kouzelnou funkci `deployMockContract()`, která vytváří kontrakt pouze pomocí _abi_ rozhraní: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Nyní s peněženkou i nasazeným ERC20 můžeme pokračovat a nasadit kontrakt `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Tím je naše funkce `beforeEach()` hotová. Váš soubor `AmIRichAlready.test.ts` by zatím měl vypadat takto: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Napišme si první test pro kontrakt `AmIRichAlready`. Co myslíte, o čem by měl být náš test? Ano, máte pravdu! Měli bychom zkontrolovat, jestli už jsme bohatí :) - -Ale počkejte chvilku. Jak bude náš mockovaný kontrakt vědět, jaké hodnoty má vrátit? Neimplementovali jsme žádnou logiku pro funkci `balanceOf()`. I zde může Waffle pomoci. Náš mockovaný kontrakt má teď několik nových vychytávek: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -S touto znalostí můžeme konečně napsat náš první test: - -```typescript -it("vrátí false, pokud má peněženka méně než 1000000 tokenů", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Rozdělme si tento test na části: - -1. Nastavíme náš mock kontrakt ERC20, aby vždy vracel zůstatek 999999 tokenů. -2. Zkontrolujeme, zda metoda `contract.check()` vrací `false`. - -Jsme připraveni to spustit: - -![Jeden test prochází](./test-one.png) - -Takže test funguje, ale... stále je co zlepšovat. Funkce `balanceOf()` bude vždy vracet 999999. Můžeme to vylepšit tím, že určíme peněženku, pro kterou by funkce měla něco vrátit – stejně jako u skutečného kontraktu: - -```typescript -it("vrátí false, pokud má peněženka méně než 1000001 tokenů", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Zatím jsme testovali pouze případ, kdy nejsme dostatečně bohatí. Otestujme místo toho opak: - -```typescript -it("vrátí true, pokud má peněženka alespoň 1000001 tokenů", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Spustíte testy... - -![Dva testy procházejí](test-two.png) - -...a je to! Zdá se, že náš kontrakt funguje, jak má :) - -## Testování volání kontraktů {#testing-contract-calls} - -Pojďme si shrnout, co jsme dosud udělali. Otestovali jsme funkčnost našeho kontraktu `AmIRichAlready` a zdá se, že funguje správně. To znamená, že jsme hotovi, že? Ne tak docela! Waffle nám umožňuje testovat náš kontrakt ještě důkladněji. Ale jak přesně? V arzenálu Waffle jsou matchery `calledOnContract()` a `calledOnContractWith()`. Umožní nám zkontrolovat, zda náš kontrakt zavolal mock kontrakt ERC20. Zde je základní test s jedním z těchto matcherů: - -```typescript -it("kontroluje, zda kontrakt zavolal balanceOf na tokenu ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Můžeme jít ještě dál a vylepšit tento test s druhým matcherem, o kterém jsem vám říkal: - -```typescript -it("kontroluje, zda kontrakt zavolal balanceOf s určitou peněženkou na tokenu ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Zkontrolujme, zda jsou testy správné: - -![Tři testy procházejí](test-three.png) - -Skvělé, všechny testy jsou zelené. - -Testování volání kontraktů s Waffle je super snadné. A tady je ta nejlepší část. Tyto matchery fungují jak s normálními, tak s mockovanými kontrakty! Je to proto, že Waffle zaznamenává a filtruje volání EVM, místo aby vkládal kód, jak je tomu u populárních testovacích knihoven pro jiné technologie. - -## Cílová rovinka {#the-finish-line} - -Výborně! Nyní víte, jak používat Waffle k testování volání kontraktů a dynamickému mockování kontraktů. Existuje mnohem více zajímavých funkcí k objevení. Doporučuji ponořit se do dokumentace Waffle. - -Dokumentace Waffle je k dispozici [zde](https://ethereum-waffle.readthedocs.io/). - -Zdrojový kód pro tento tutoriál naleznete [zde](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutoriály, které by vás také mohly zajímat: - -- [Testování chytrých kontraktů s Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 844937f21cf..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Návod na ukázkový Hello World s Waffle, hardhat a ethers" -description: "Vytvořte svůj první Waffle projekt s hardhat a ethers.js" -author: "MiZiet" -tags: - [ - "waffle", - "smart kontrakt účty", - "solidity", - "testování", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: cs -published: 2020-10-16 ---- - -V tomto [Waffle](https://ethereum-waffle.readthedocs.io) tutoriálu se naučíme, jak nastavit jednoduchý projekt s chytrým kontraktem "Hello world" s použitím [hardhat](https://hardhat.org/) a [ethers.js](https://docs.ethers.io/v5/). Poté se naučíme, jak do našeho chytrého kontraktu přidat novou funkcionalitu a jak ji otestovat pomocí Waffle. - -Začněme vytvořením nového projektu: - -```bash -yarn init -``` - -nebo - -```bash -npm init -``` - -a instalací požadovaných balíčků: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -nebo - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Dalším krokem je vytvoření ukázkového projektu hardhat spuštěním `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Vyberte `Create a sample project` - -Struktura našeho projektu by měla vypadat takto: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Pojďme se nyní podívat na některé z těchto souborů: {#now-lets-talk} - -- Greeter.sol – náš chytrý kontrakt napsaný v Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Náš chytrý kontrakt lze rozdělit na tři části: - -1. konstruktor – kde deklarujeme proměnnou typu string s názvem `greeting`, -2. funkce greet – funkce, která po zavolání vrátí `greeting`, -3. funkce setGreeting – funkce, která nám umožňuje změnit hodnotu `greeting`. - -- sample-test.js – náš soubor s testy - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Další krok spočívá v kompilaci našeho kontraktu a spuštění testů: {#compiling-and-testing} - -Waffle testy používají Mocha (testovací framework) s Chai (knihovna asercí). Vše, co musíte udělat, je spustit `npx hardhat test` a počkat, až se objeví následující zpráva. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Zatím to vypadá skvěle, pojďme do projektu přidat trochu na složitosti {#adding-complexity} - -Představte si situaci, kde někdo vloží prázdný řetězec jako pozdrav. To by nebyl moc vřelý pozdrav, že? -Postarejme se, aby se to nestalo: - -Chceme použít funkci `revert` ze Solidity, když někdo předá prázdný řetězec. Dobrou zprávou je, že tuto funkcionalitu můžeme snadno otestovat pomocí Waffle chai matcheru `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Vypadá to, že náš nový test neprošel: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Pojďme tuto funkcionalitu implementovat do našeho chytrého kontraktu: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Nyní naše funkce setGreeting vypadá takto: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Pojďme znovu spustit testy: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Výborně! Dali jste to! :) - -### Závěr {#conclusion} - -Vytvořili jsme jednoduchý projekt s Waffle, Hardhat a ethers.js. Naučili jsme se, jak nastavit projekt, přidat test a implementovat novou funkcionalitu. - -Pro více skvělých chai matcherů k testování vašich chytrých kontraktů se podívejte do [oficiální dokumentace Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index c8379ef1b5b..00000000000 --- a/public/content/translations/cs/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: "Testování jednoduchého chytrého kontraktu s knihovnou Waffle" -description: "Návod pro začátečníky" -author: Ewa Kowalska -tags: - [ - "smart kontrakt účty", - "solidity", - "Waffle", - "testování" - ] -skill: beginner -lang: cs -published: 2021-02-26 ---- - -## V tomto návodu se naučíte, jak {#in-this-tutorial-youll-learn-how-to} - -- Testovat změny zůstatku peněženky -- Testovat emisi událostí se zadanými argumenty -- Ověřit, že byla transakce vrácena - -## Předpoklady {#assumptions} - -- Můžete vytvořit nový projekt v JavaScriptu nebo TypeScriptu -- Máte nějaké základní zkušenosti s testy v JavaScriptu -- Použili jste nějaké správce balíčků jako yarn nebo npm -- Máte velmi základní znalosti chytrých kontraktů a Solidity - -## Začínáme {#getting-started} - -Tento návod ukazuje nastavení a spuštění testu pomocí yarn, ale není problém, pokud dáváte přednost npm – poskytnu správné odkazy na oficiální [dokumentaci](https://ethereum-waffle.readthedocs.io/en/latest/index.html) Waffle. - -## Instalace závislostí {#install-dependencies} - -[Přidejte](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) závislosti ethereum-waffle a typescript do vývojářských závislostí vašeho projektu. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Příklad chytrého kontraktu {#example-smart-contract} - -Během tohoto návodu budeme pracovat na jednoduchém příkladu chytrého kontraktu – EtherSplitter. Nedělá toho moc kromě toho, že umožňuje komukoli poslat nějaké wei a rovnoměrně je rozdělit mezi dva předdefinované příjemce. -Funkce `split` vyžaduje, aby byl počet wei sudý, jinak se vrátí zpět. Pro oba příjemce provádí převod wei následovaný emisí události Transfer. - -Vložte úryvek kódu EtherSplitter do `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Lichá částka wei není povolena'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Kompilace kontraktu {#compile-the-contract} - -Pro [kompilaci](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) kontraktu přidejte následující položku do souboru package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Dále vytvořte konfigurační soubor Waffle v kořenovém adresáři projektu – `waffle.json` – a poté tam vložte následující konfiguraci: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Spusťte `yarn build`. Výsledkem je, že se objeví adresář `build` s kompilovaným kontraktem EtherSplitter ve formátu JSON. - -## Nastavení testu {#test-setup} - -Testování pomocí Waffle vyžaduje použití Chai matchers a Mocha, takže je musíte [přidat](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) do svého projektu. Aktualizujte soubor package.json a přidejte položku `test` do části se skripty: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Chcete-li [spustit](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) své testy, stačí spustit `yarn test` . - -## Testování {#testing} - -Nyní vytvořte adresář `test` a vytvořte nový soubor `test\EtherSplitter.test.ts`. -Zkopírujte úryvek níže a vložte jej do našeho testovacího souboru. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Rozdělovač etheru", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // sem přidejte testy -}) -``` - -Pár slov na úvod. -`MockProvider` poskytuje testovací verzi blockchainu. Poskytuje také testovací peněženky, které nám poslouží k testování kontraktu EtherSplitter. Můžeme získat až deset peněženek zavoláním metody `getWallets()` na providera. V příkladu získáme tři peněženky – pro odesílatele a pro dva příjemce. - -Dále deklarujeme proměnnou nazvanou „splitter“ – to je náš testovací kontrakt EtherSplitter. Vytváří se před každým spuštěním jednotlivého testu metodou `deployContract`. Tato metoda simuluje nasazení kontraktu z peněženky předané jako první parametr (v našem případě peněženky odesílatele). Druhým parametrem je ABI a bytecode testovaného kontraktu – předáme tam soubor json zkompilovaného kontraktu EtherSplitter z adresáře `build`. Třetím parametrem je pole s argumenty konstruktoru kontraktu, což jsou v našem případě dvě adresy příjemců. - -## changeBalances {#changebalances} - -Nejprve zkontrolujeme, zda metoda split skutečně změní zůstatky v peněženkách příjemců. Pokud rozdělíme 50 wei z účtu odesílatele, očekávali bychom, že zůstatky obou příjemců se zvýší o 25 wei. Použijeme matcher `changeBalances` od Waffle: - -```ts -it("Změní zůstatky účtů", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Jako první parametr matcheru předáváme pole peněženek příjemců a jako druhý – pole očekávaných navýšení na odpovídajících účtech. -Pokud bychom chtěli zkontrolovat zůstatek jedné konkrétní peněženky, mohli bychom také použít matcher `changeBalance`, který nevyžaduje předávání polí, jako v příkladu níže: - -```ts -it("Změní zůstatek účtu", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Všimněte si, že v obou případech `changeBalance` a `changeBalances` předáváme funkci split jako callback, protože matcher potřebuje přístup ke stavu zůstatků před a po volání. - -Dále otestujeme, zda byla po každém převodu wei emitována událost Transfer. Obrátíme se na další matcher od Waffle: - -## Emit {#emit} - -```ts -it("Emituje událost při převodu na prvního příjemce", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emituje událost při převodu na druhého příjemce", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -Matcher `emit` nám umožňuje zkontrolovat, zda kontrakt emitoval událost při volání metody. Jako parametry matcheru `emit` poskytneme testovací kontrakt, u kterého předpokládáme emisi události, spolu s názvem této události. V našem případě je testovacím kontraktem `splitter` a název události – `Transfer`. Můžeme také ověřit přesné hodnoty argumentů, se kterými byla událost emitována – do matcheru `withArgs` předáme tolik argumentů, kolik naše deklarace události očekává. V případě kontraktu EtherSplitter předáváme adresy odesílatele a příjemce spolu s převedenou částkou wei. - -## revertedWith {#revertedwith} - -Jako poslední příklad zkontrolujeme, zda byla transakce vrácena v případě lichého počtu wei. Použijeme matcher `revertedWith`: - -```ts -it("Vrátí zpět, když je částka wei lichá", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Lichá částka wei není povolena" - ) -}) -``` - -Test, pokud projde, nás ujistí, že transakce byla skutečně vrácena. Musí však také existovat přesná shoda mezi zprávami, které jsme předali v příkazu `require`, a zprávou, kterou očekáváme v `revertedWith`. Pokud se vrátíme ke kódu kontraktu EtherSplitter, v příkazu `require` pro částku wei poskytujeme zprávu: ‚Lichá částka wei není povolena‘. Ta se shoduje se zprávou, kterou očekáváme v našem testu. Pokud by se neshodovaly, test by selhal. - -## Gratulujeme! {#congratulations} - -Udělali jste první velký krok k testování chytrých kontraktů s Waffle! diff --git a/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 2ef6b047122..00000000000 --- a/public/content/translations/es/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1146 +0,0 @@ ---- -title: Probar tokens ERC-20 con Waffle -description: "Aprende cómo probar smart contracts en Solidity y utiliza comparadores de smart contracts con Waffle." -author: Vladislav Starostenko -tags: - - "waffle" - - "contratos inteligentes" - - "solidity" - - "pruebas" - - "erc-20" -skill: intermediate -lang: es -published: 2020-10-16 ---- - -En este tutorial aprenderás como: - -- Escribir pruebas para smart contracts con Waffle -- Usar algunos de los matchers populares para probar smart contracts con Waffle - -Supuestos: - -- sabes cómo usar una terminal, -- puedes crear un proyecto nuevo en `JavaScript`, -- has escrito líneas de código en `Solidity`, -- has escrito pruebas en `JavaScript`, -- has usado `yarn` o `npm`, o el instalador de paquetes de JavaScript. - -Si una de las suposiciones previas no encajan, o no planeas reproducir el código en este artículo, puede ser que no tengas ningún inconveniente leyendo este articulo. - -## Un vistazo a Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) es la biblioteca más avanzada para escribir y probar smart contracts. - -Funciona con ethers-js, un [API de JavaScript](/developers/docs/apis/javascript/). - -¡Puedes leer más detalles en la [documentación de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial rápido {#the-quick-tutorial} - -Lo primero es lo primero, crea un nuevo proyecto `JavaScript` o `TypeScript` ( Utiliza `TS`, pero si utilizas `JS` no hay problema) : - -Algo como esto: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Paso #1: Instala Waffle en tu proyecto [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Para comenzar, instale `ethereum-waffle`. En este tutorial usaré `yarn`; para instalar `ethereum-waffle`, ejecute: - -```bash - yarn add --dev ethereum-waffle -``` - -## Paso #2: Escribe un contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -En este tutorial, usaré el token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) de [OpenZeppelin](https://openzeppelin.com). - -Por lo tanto, añade `OpenZeppelin` instalándolo con `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Luego cree el contrato `BasicToken.sol` en el directorio `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Paso #3: Compila tu contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Para compilar su contrato inteligente, agregue la siguiente entrada en el `package.json` de su proyecto: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -También, agregue el archivo `waffle.json` en el directorio principal de su proyecto. - -Un ejemplo de la configuración de `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Puede leer más acerca de la configuración de Waffle [aquí](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Luego ejecute simplemente `yarn build` para compilar su contrato inteligente. - -Debería ver que Waffle ha compilado el contrato y ha ubicado la salida JSON resultante dentro del directorio `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` - -
- -## Paso #4: Compila tu contrato inteligente [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Paso #4.1: Instala Waffle en tu proyecto [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Después de haber creado con éxito un Contrato Inteligente, podemos probarlo. Utilizaremos `Waffle` para hacerlo. - -Las pruebas en `Waffle` se escriben usando `Mocha` junto con `Chai`. Podemos usar un entorno de prueba diferente, pero los emparejadores `Waffle` solo funcionan con `Chai`. - -Por lo tanto, necesitamos añadir `Chai` a nuestras dependencias : - -```bash - yarn add --dev mocha chai -``` - -### Paso #4.2: Escribe un contrato inteligente de prueba [Link](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Para escribir nuestra prueba necesitamos crear el archivo `BasicToken.test.ts` en nuestro directorio de pruebas. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Por lo tanto, utilizamos el método `deployContract` de `Waffle`para desplegar nuestro token. Como argumentos, debemos pasar `wallet`, el archivo json compilado de nuestro contrato y el balance por defecto. - -`Waffle` también nos permite crear un `wallet`, lo que hace muy sencillo implementar un contrato. - -Puede leer más sobre `monedero` [aquí](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) y puede leer más sobre la función de despliegue [aquí](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Vamos a escribir una prueba simple para comprobar el balance de nuestra cartera. Desde que enviamos el valor 1000 durante el despliegue de nuestro contrato, el saldo de nuestra cartera debe ser de 1000 tokens, que podemos comprobar en la primera prueba. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Para ejecutar la prueba usa `yarn test` - -### Paso #4.3 Emisión de eventos [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -En este tutorial, quiero mostrarte los emparejadores más útiles de `Waffle`, así que comencemos con el primero. - -`Waffle` nos permite probar qué eventos se emiten. - -En este tutorial, probaré el método `transfer` de nuestro contrato. - -En esta prueba, haré una transferencia de una cartera a otra y comprobaré si el evento de `transfer` fue llamado. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Además, una gran ventaja de este emparejador es que podemos comprobar con qué argumentos se llamó este evento añadiendo `withArgs` a nuestra prueba. - -¡Esto nos permitirá estar seguros de que nuestra función se llama correctamente! - -### Paso #4.4 Revertir con mensaje [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` nos permite probar qué eventos se emiten. - -Utilizaremos `revertedWith` matcher en nuestra prueba para comprobarlo. - -Podemos escribir una prueba en la que realizaremos una transferencia por una cantidad mayor que la que tenemos en nuestra cartera. Y luego comprobaremos si la transacción se ha revertido con el mensaje exacto! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Paso #4.5 Cambiar token-balance [Enlace al documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`¡Waffle` nos permite comprobar si hay cambios en los balances de las carteras! - -Podemos usar el comparador `changeTokenBalance` para verificar el cambio de balance o el `changeTokenBalances` para una cuenta múltiple. - -El emparejador puede aceptar `números`, `cadenas` y `números` como un cambio de balance. mientras que la dirección debe especificarse como una cartera o un contrato. - -Vamos a escribir la siguiente prueba: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Lo anterior es una prueba para una única cartera. - -Y el siguiente para múltiples carteras: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -Se espera que la transacción se pase como callback (necesitamos comprobar el saldo antes de la llamada) o como una respuesta de la transacción. - -## Felicitaciones {#congratulations} - -**¡Felicitaciones! Lo has conseguido a través de mi tutorial. Has dado tu primer gran paso para probar contratos inteligentes con Waffle.** - -**Código de este tutorial que puedes encontrar [aquí](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Más documentación sobre `Waffle` disponible [aquí](https://getwaffle.io).** diff --git a/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 7e04e787825..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: simulación dinámica y pruebas de llamadas a contratos" -description: "Tutorial avanzado de Waffle para el uso de simulaciones dinámicas y pruebas de llamadas a contratos" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "contratos Inteligentes", - "Solidity", - "pruebas", - "simular" - ] -skill: intermediate -lang: es -published: 2020-11-14 ---- - -## ¿De qué trata este tutorial? {#what-is-this-tutorial-about} - -En este tutorial aprenderás cómo: - -- utilizar simulación dinámica -- comprobar las interacciones entre contratos inteligentes - -Suposiciones: - -- ya sabes cómo escribir un contrato inteligente simple en `Solidity` -- ya sabes utilizar `JavaScript` y `TypeScript` -- ya has hecho otros tutoriales de `Waffle` o sabes algunas cosas sobre él - -## Simulación dinámica {#dynamic-mocking} - -¿Por qué es útil la simulación dinámica? Bueno, nos permite escribir pruebas unitarias en lugar de pruebas de integración. ¿Y eso, qué significa? Significa que no tenemos que preocuparnos por las dependencias de los contratos inteligentes, por lo que podremos probarlos de forma aislada. Déjame mostrarte cómo puedes hacerlo. - -### **1. Proyecto** {#1-project} - -Antes de comenzar debemos preparar un proyecto simple node.js: - -```bash -mkdir simulacion-dinamica -cd simulacion-dinamica -mkdir contracts src - -yarn init -# o si estás usando npm -npm init -``` - -Comencemos agregando dependencias de typescript y prueba: mocha y chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# o si estás usando npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Ahora agreguemos `Waffle` y `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# o si estás usando npm -npm install ethereum-waffle ethers --save-dev -``` - -La estructura de tu proyecto debería verse así: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Contrato inteligente** {#2-smart-contract} - -Para comenzar una simulación dinámica, necesitamos un contrato inteligente con dependencias. No te preocupes, ¡yo me encargo! - -Aquí hay un contrato inteligente simple escrito en `Solidity` cuyo único propósito es comprobar si somos ricos. Utiliza el token ERC20 para comprobar si tenemos suficientes tokens. Ponlo en `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Como queremos utilizar la simulación dinámica no necesitamos el ERC20 completo, por eso estamos utilizando la interfaz de IERC20 con sólo una función. - -¡Es hora de construir este contrato! Para ello utilizaremos `Waffle`. Primero, vamos a crear un archivo de configuración simple `waffle.json` que especifica las opciones de compilación. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Ahora estamos listos para crear el contrato con Waffle: - -```bash -npx waffle -``` - -Fácil, ¿verdad? En la carpeta `build/` aparecieron dos archivos correspondientes al contrato y la interfaz. Los utilizaremos luego para las pruebas. - -### **3. Pruebas** {#3-testing} - -Creemos un archivo llamado `AmIRichAlready.test.ts` para estas pruebas. Antes que nada, tenemos que gestionar las importaciones. Las necesitaremos luego: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Aparte de las dependencias de JS, necesitamos importar nuestro contrato compilado y la interfaz: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle utiliza `chai` para las pruebas. Sin embargo, antes de utilizarlo, debemos insertar los emparejadores de Waffle en el propio chai: - -```typescript -use(solidity) -``` - -Necesitamos implementar una función `beforeEach()` que restablezca el estado del contrato antes de cada prueba. Pensemos primero en lo que necesitamos allí. Para desplegar un contrato, necesitamos dos cosas: una billetera y un contrato ERC20 desplegado para pasarlo como argumento del contrato `AmIRichAlready`. - -Primero, creamos la billetera: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Luego debemos desplegar un contrato ERC20. Aquí está la parte difícil: sólo tenemos una interfaz. Esta es la parte en que Waffle viene a salvarnos. Waffle tiene una función mágica `deployMockContract()` que crea un contrato usando únicamente el _abi_ de la interfaz: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Ahora con la billetera y el ERC20 desplegado, podemos continuar e implementar el contrato `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Con todo eso, nuestra función `beforeEach()` está terminada. Hasta aquí, tu archivo `AmIRichAlready.test.ts` debería verse así: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Escribamos la primera prueba para el contrato `AmIRichAlready`. ¿De qué crees que debería ser nuestra prueba? ¡Sí, tienes razón! Deberíamos comprobar si ya somos ricos :) - -Pero espera un segundo. ¿Cómo sabrá nuestro contrato simulado qué valores devolver? No hemos implementado ninguna lógica para la función `balanceOf()`. Nuevamente, Waffle nos puede ayudar. Nuestro contrato simulado tiene algunas cosas nuevas: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Con este conocimiento podemos, finalmente, escribir nuestra primera prueba: - -```typescript -it("devuelve «false» si la billetera tiene menos de 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Separemos esta prueba en partes: - -1. Establecimos nuestro contrato ERC20 simulado para devolver siempre un saldo de 999999 tokens. -2. Comprobar si el método `contract.check()` devuelve `false`. - -Estamos listos para liberar a la bestia: - -![Una prueba superada](./test-one.png) - -Así que la prueba funciona, pero... todavía hay margen de mejora. La función `balanceOf()` siempre devolverá 999999. Podemos mejorarla especificando una billetera para la que la función devolverá algo, como un contrato real: - -```typescript -it("devuelve «false» si la billetera tiene menos de 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Hasta el momento, sólo probamos el caso donde aún no somos suficientemente ricos. Probemos el opuesto esta vez: - -```typescript -it("devuelve «true» si la billetera tiene al menos 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Ejecutas las pruebas... - -![Dos pruebas superadas](./test-two.png) - -... ¡y aquí está! Nuestro contrato parece funcionar según lo previsto :) - -## Prueba de llamadas a contratos {#testing-contract-calls} - -Veamos lo que hicimos hasta ahora. Hemos probado la funcionalidad de nuestro contrato `AmIRichAlready` y parece que funciona correctamente. Esto significa que terminamos, ¿verdad? ¡No exactamente! Waffle nos permite probar nuestro contrato aún más. ¿Pero cómo? Bueno, en el arsenal de Waffle están los emparejadores `calledOnContract()` y `calledOnContractWith()`. Nos permitirán comprobar si nuestro contrato llamó al contrato simulado de ERC20. Aquí hay una prueba básica con uno de estos emparejadores: - -```typescript -it("comprueba si el contrato llamó a balanceOf en el token ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Podemos ir aún más lejos y mejorar esta prueba con el otro emparejador del que te hablé: - -```typescript -it("comprueba si el contrato llamó a balanceOf con una billetera determinada en el token ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Vamos a comprobar si las pruebas fueron correctas: - -![Tres pruebas superadas](./test-three.png) - -Genial, todas las pruebas están verdes. - -Probar las llamadas de contrato con Waffle es muy fácil. Y aquí está la mejor parte. ¡Estos emparejadores funcionan tanto con contratos normales como simulados! Esto se debe a que Waffle registra y filtra las llamadas de la EVM en lugar de inyectar código, como es el caso de las librerías de prueba populares para otras tecnologías. - -## La recta final {#the-finish-line} - -¡Enhorabuena! Ahora sabes cómo usar Waffle para probar las llamadas de contrato y contratos simulados de forma dinámica. Hay características mucho más interesantes que descubrir. Recomiendo revisar la documentación de Waffle. - -La documentación de Waffle está disponible [aquí](https://ethereum-waffle.readthedocs.io/). - -El código fuente de este tutorial se puede encontrar [aquí](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Otros tutoriales que podrían interesarte: - -- [Prueba de contratos inteligentes con Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 62d3105a3dc..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Tutorial de Waffle «Hola, mundo» con Hardhat y ethers" -description: Cree su primer proyecto de Waffle con Hardhat y ethers.js -author: "MiZiet" -tags: - [ - "waffle", - "contratos Inteligentes", - "Solidity", - "pruebas", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: es -published: 2020-10-16 ---- - -En este tutorial de [Waffle](https://ethereum-waffle.readthedocs.io), aprenderemos a configurar un proyecto simple de contrato inteligente «Hola, mundo», utilizando [hardhat](https://hardhat.org/) y [ethers.js](https://docs.ethers.io/v5/). Luego aprenderemos cómo añadir una nueva funcionalidad a nuestro contrato inteligente y cómo probarlo con Waffle. - -Empecemos creando un nuevo proyecto: - -```bash -yarn init -``` - -o - -```bash -npm init -``` - -y la instalación de los paquetes necesarios: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -o - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -El siguiente paso es crear un proyecto de muestra de Hardhat ejecutando `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Seleccione `Create a sample project` - -La estructura de nuestro proyecto debería verse así: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Ahora hablemos de algunos de estos archivos: {#now-lets-talk} - -- Greeter.sol: nuestro contrato inteligente escrito en Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Desplegando un Greeter con el saludo:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Cambiando el saludo de '%s' a '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Nuestro contrato inteligente se puede dividir en tres partes: - -1. constructor: donde declaramos una variable de tipo cadena llamada `greeting`, -2. función greet: una función que devolverá el `greeting` al ser invocada, -3. función setGreeting: una función que nos permite cambiar el valor de `greeting`. - -- sample-test.js: nuestro archivo de pruebas - -```js -describe("Greeter", function () { - it("Debería devolver el nuevo saludo una vez que se ha cambiado", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### El siguiente paso consiste en compilar nuestro contrato y ejecutar las pruebas: {#compiling-and-testing} - -Las pruebas de Waffle utilizan Mocha (un marco de pruebas) con Chai (una biblioteca de aserciones). Todo lo que tiene que hacer es ejecutar `npx hardhat test` y esperar a que aparezca el siguiente mensaje. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Todo parece ir bien hasta ahora. Añadamos un poco más de complejidad a nuestro proyecto {#adding-complexity} - -Imagine una situación en la que alguien añade una cadena vacía como saludo. No sería un saludo muy cálido, ¿verdad? -Asegurémonos de que eso no ocurra: - -Queremos usar el `revert` de Solidity cuando alguien pase una cadena vacía. Lo bueno es que podemos probar fácilmente esta funcionalidad con el comparador de Chai de Waffle `to.be.revertedWith()`. - -```js -it("Debería revertir al pasar una cadena vacía", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "El saludo no debe estar vacío" - ) -}) -``` - -Parece que nuestra nueva prueba no ha pasado: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implementemos esta funcionalidad en nuestro contrato inteligente: - -```solidity -require(bytes(_greeting).length > 0, "El saludo no debe estar vacío"); -``` - -Ahora, nuestra función setGreeting se ve así: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "El saludo no debe estar vacío"); -console.log("Cambiando el saludo de '%s' a '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Ejecutemos las pruebas de nuevo: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -¡Enhorabuena! ¡Lo ha conseguido! :) - -### Conclusión {#conclusion} - -Hemos creado un proyecto sencillo con Waffle, Hardhat y ethers.js. Hemos aprendido a configurar un proyecto, añadir una prueba e implementar una nueva funcionalidad. - -Para ver más comparadores de Chai excelentes con los que probar sus contratos inteligentes, consulte la [documentación oficial de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 4bf3eb81b4c..00000000000 --- a/public/content/translations/es/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: Prueba de un contrato inteligente simple con la biblioteca Waffle -description: Tutorial para principiantes -author: Ewa Kowalska -tags: - [ - "contratos Inteligentes", - "Solidity", - "Waffle", - "pruebas" - ] -skill: beginner -lang: es -published: 2021-02-26 ---- - -## En este tutorial aprenderá a {#in-this-tutorial-youll-learn-how-to} - -- Probar los cambios en el saldo de la billetera -- Probar la emisión de eventos con argumentos específicos -- Afirmar que una transacción ha sido revertida - -## Supuestos {#assumptions} - -- Puede crear un nuevo proyecto de JavaScript o TypeScript -- Tiene algo de experiencia básica con pruebas en JavaScript -- Ha usado algunos administradores de paquetes como yarn o npm -- Posee conocimientos muy básicos sobre contratos inteligentes y Solidity - -## Primeros pasos {#getting-started} - -El tutorial demuestra la configuración y ejecución de la prueba usando yarn, pero no hay problema si prefiere npm. Proporcionaré las referencias adecuadas a la [documentación](https://ethereum-waffle.readthedocs.io/en/latest/index.html) oficial de Waffle. - -## Instalar dependencias {#install-dependencies} - -[Añada](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) las dependencias ethereum-waffle y typescript a las dependencias de desarrollo de su proyecto. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Ejemplo de contrato inteligente {#example-smart-contract} - -Durante el tutorial trabajaremos en un ejemplo de contrato inteligente simple: EtherSplitter. No hace mucho más que permitir que cualquiera envíe wei y los divida en partes iguales entre dos receptores predefinidos. -La función `split` requiere que la cantidad de wei sea par; de lo contrario, se revertirá. Para ambos receptores, realiza una transferencia de wei seguida de la emisión del evento `Transfer`. - -Coloque el fragmento de código de EtherSplitter en `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'No se permite una cantidad impar de wei'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Compilar el contrato {#compile-the-contract} - -Para [compilar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) el contrato, añada la siguiente entrada al archivo package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -A continuación, cree el archivo de configuración de Waffle en el directorio raíz del proyecto, `waffle.json`, y pegue allí la siguiente configuración: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Ejecute `yarn build`. Como resultado, aparecerá el directorio `build` con el contrato EtherSplitter compilado en formato JSON. - -## Configuración de la prueba {#test-setup} - -Probar con Waffle requiere el uso de los matchers de Chai y Mocha, por lo que necesita [añadirlos](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) a su proyecto. Actualice su archivo package.json y añada la entrada `test` en la parte de scripts: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Si desea [ejecutar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) sus pruebas, simplemente ejecute `yarn test`. - -## Pruebas {#testing} - -Ahora cree el directorio `test` y el nuevo archivo `test\EtherSplitter.test.ts`. -Copie el siguiente fragmento y péguelo en nuestro archivo de prueba. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // añada las pruebas aquí -}) -``` - -Unas palabras antes de empezar. -`MockProvider` viene con una versión de simulación de la cadena de bloques. También proporciona billeteras de simulación que nos servirán para probar el contrato EtherSplitter. Podemos obtener hasta diez billeteras llamando al método `getWallets()` en el proveedor. En el ejemplo, obtenemos tres billeteras: para el emisor y para dos receptores. - -A continuación, declaramos una variable llamada «splitter», que es nuestro contrato de simulación EtherSplitter. Se crea antes de cada ejecución de una única prueba mediante el método `deployContract`. Este método simula la implementación de un contrato desde la billetera pasada como primer parámetro (la billetera del emisor en nuestro caso). El segundo parámetro es la ABI y el bytecode del contrato probado. Allí pasamos el archivo json del contrato EtherSplitter compilado desde el directorio `build`. El tercer parámetro es un array con los argumentos del constructor del contrato, que en nuestro caso son las dos direcciones de los receptores. - -## changeBalances {#changebalances} - -Primero, comprobaremos si el método `split` cambia realmente los saldos de las billeteras de los receptores. Si dividimos 50 wei de la cuenta del emisor, esperaríamos que los saldos de ambos receptores aumentaran en 25 wei. Usaremos el matcher `changeBalances` de Waffle: - -```ts -it("Cambia los saldos de las cuentas", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Como primer parámetro del matcher, pasamos un array de las billeteras de los receptores y, como segundo, un array de los aumentos esperados en las cuentas correspondientes. -Si quisiéramos comprobar el saldo de una billetera específica, también podríamos usar el matcher `changeBalance`, que no requiere pasar arrays, como en el siguiente ejemplo: - -```ts -it("Cambia el saldo de la cuenta", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Tenga en cuenta que en ambos casos de `changeBalance` y `changeBalances` pasamos la función `split` como un callback porque el matcher necesita acceder al estado de los saldos antes y después de la llamada. - -A continuación, probaremos si el evento `Transfer` se emitió después de cada transferencia de wei. Pasaremos a otro matcher de Waffle: - -## Emit {#emit} - -```ts -it("Emite un evento en la transferencia al primer receptor", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emite un evento en la transferencia al segundo receptor", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -El matcher `emit` nos permite comprobar si un contrato emitió un evento al llamar a un método. Como parámetros para el matcher `emit`, proporcionamos el contrato de simulación que predecimos que emitirá el evento, junto con el nombre de ese evento. En nuestro caso, el contrato de simulación es `splitter` y el nombre del evento es `Transfer`. También podemos verificar los valores precisos de los argumentos con los que se emitió el evento: pasamos tantos argumentos al matcher `withArgs` como espera nuestra declaración de evento. En el caso del contrato EtherSplitter, pasamos las direcciones del emisor y del receptor junto con la cantidad de wei transferida. - -## revertedWith {#revertedwith} - -Como último ejemplo, comprobaremos si la transacción fue revertida en caso de una cantidad impar de wei. Usaremos el matcher `revertedWith`: - -```ts -it("Se revierte cuando la cantidad de wei es impar", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "No se permite una cantidad impar de wei" - ) -}) -``` - -La prueba, si se supera, nos asegurará que la transacción fue revertida. Sin embargo, también debe haber una coincidencia exacta entre los mensajes que pasamos en la declaración `require` y el mensaje que esperamos en `revertedWith`. Si volvemos al código del contrato EtherSplitter, en la declaración `require` para la cantidad de wei, proporcionamos el mensaje: «No se permite una cantidad impar de wei». Esto coincide con el mensaje que esperamos en nuestra prueba. Si no fueran iguales, la prueba fallaría. - -## ¡Felicitaciones! {#congratulations} - -¡Ha dado su primer gran paso hacia la prueba de contratos inteligentes con Waffle! diff --git a/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 88a567b45fd..00000000000 --- a/public/content/translations/fr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1147 +0,0 @@ ---- -title: Tester les jetons ERC-20 avec Waffle -description: Découvrez comment tester les contrats intelligents Solidity et utiliser des correspondances de contrats intelligents avec Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "contrats intelligents" - - "solidity" - - "test" - - "erc-20" -skill: intermediate -lang: fr -published: 2020-10-16 ---- - -Dans ce tutoriel, vous apprendrez comment : - -- Écrire des tests pour les contrats intelligents avec Waffle -- Utiliser des correspondances populaires pour tester des contrats intelligents avec Waffle - -Prérequis : - -- vous savez utiliser un terminal ou une invite de commandes, -- vous savez créer un nouveau projet `JavaScript`, -- Vous avez déjà écrit quelques lignes de code en `Solidity`, -- vous avez déjà écrit quelques tests en `JavaScript`, -- vous avez déjà utilisé `yarn` ou `npm`, un installateur de paquets JavaScript. - -Encore une fois, si l'un de ces éléments n'est pas correct ou si vous ne prévoyez pas de reproduire l'exact code de cet article, il vous sera possible de comprendre son contenu sans grande difficulté. - -## Quelques mots sur Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) est la bibliothèque la plus avancée pour écrire et tester les contrats intelligents. - -Fonctionne avec l'[API JavaScript](/developers/docs/apis/javascript/) ethers-js. - -Vous pouvez trouver de plus amples détails dans la [documentation Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation) ! - -## Le tutoriel rapide {#the-quick-tutorial} - -Tout d'abord, créez un nouveau projet `JavaScript` ou `TypeScript` (Je vais utiliser `TS`, mais si vous utilisez `JS` ce n'est pas un problème) : - -Quelque chose comme ceci : - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Étape #1 : Installez Waffle dans votre projet ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)) {#step-1-install-waffle-in-your-project} - -Pour commencer, installez `ethereum-waffle`. Dans ce tutoriel, j'utiliserai `yarn`, donc pour installer `ethereum-waffle` exécutez : - -```bash - yarn add --dev ethereum-waffle -``` - -## Étape #2 : Écrire un contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract)) {#step-2-write-a-smart-contract} - -Dans ce tutoriel, j'utiliserai le jeton [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) de [OpenZeppelin](https://openzeppelin.com). - -Il convient donc d'ajouter `OpenZeppelin` en l'installant avec `yarn` : - -```bash - yarn add @openzeppelin/contracts -D -``` - -Ensuite, créez le contrat `BasicToken.sol` dans le répertoire `src` : - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Exemple de classe - une classe fictive utilisant la livraison de ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Étape #3 : Compilez votre contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)) {#step-3-compile-your-smart-contract} - -Pour compiler votre contrat intelligent, ajoutez l'entrée suivante dans le `package.json` de votre projet : - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Ajoutez également le fichier `waffle.json` dans le répertoire principal de votre projet. - -Un exemple de configuration `waffle.json` : - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Vous pouvez en apprendre plus sur la configuration de Waffle [ici](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Ensuite, exécutez `yarn build` pour compiler votre contrat intelligent. - -Vous devriez voir que Waffle a compilé votre contrat et placé la sortie JSON résultante dans le répertoire `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P - -``` - -
- -## Étape #4 : Testez votre contrat intelligent ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-test-your-smart-contract} - -### Étape #4.1 Installez les dépendances nécessaires ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-1} - -Une fois que nous avons réussi à rédiger un Contrat Intelligent, nous pouvons le tester. Nous utiliserons `Waffle` pour le faire. - -Les tests dans `Waffle` sont écrits à l'aide de `Mocha` avec `Chai`. Nous pouvons utiliser un environnement de test différent, mais les correspondances `Waffle` ne fonctionnent qu'avec `Chai`. - -Nous devons donc ajouter `Chai` à nos dépendances : - -```bash - yarn add --dev mocha chai -``` - -### Étape #4.2 Créez un fichier de test ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-2} - -Pour écrire notre test, nous devons créer le fichier `BasicToken.test.ts` dans notre répertoire de test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Nous utilisons alors la méthode `deployContract` de `Waffle` pour déployer notre jeton. En tant qu'arguments, nous devons passer `wallet`, le fichier json compilé de notre contrat et le solde par défaut. - -`Waffle` nous permet également de créer un `wallet`, ce qui le rend très facile à déployer un contrat. - -Vous pouvez en apprendre plus sur `wallet` [ici](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) et vous pouvez en savoir plus sur la fonction de déploiement [ici](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Écrivons un simple test pour vérifier le solde de notre portefeuille. Depuis que nous avons soumis la valeur 1000 lors du déploiement de notre contrat, le solde de notre portefeuille doit être de 1000 jetons, ce que nous pouvons vérifier dans le premier test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Pour exécuter le test, utilisez `yarn test` - -### Étape #4.3 Événement d'émission ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events)) {#step-4-3} - -Dans ce tutoriel, nous souhaitons montrer les correspondances les plus utiles de `Waffle`, alors commençons par la première. - -`Waffle` nous permet de tester quels événements ont été émis. - -Dans ce tutoriel, nous allons tester la méthode `transfer` de notre contrat. - -Dans ce test, nous allons réaliser un transfert d'un portefeuille à l'autre en vérifiant si l'événement `Transfer` a bien été appelé. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Un autre avantage de cette correspondance est que nous pouvons vérifier avec quels arguments cet événement a été appelé en ajoutant `withArgs` à notre test. - -Cela nous permettra d'être sûrs que notre fonction est appelée correctement ! - -### Étape #4.4 Annuler avec un message ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message)) {#step-4-4} - -`Waffle` nous permet de tester le message avec lequel il a été retourné. - -Nous utiliserons la correspondance `revertedWith` dans notre test pour vérifier. - -Nous pouvons écrire un test dans lequel nous effectuerons un transfert pour un montant supérieur à celui que nous avons dans notre portefeuille. Et puis nous vérifierons si la transaction a été annulée avec le message exact ! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Étape #4.5 Change-jeton-solde ([Lien vers la documentation](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance)) {#step-4-5} - -`Waffle` nous permet de vérifier les changements dans les soldes des portefeuilles ! - -Nous pouvons utiliser la correspondance `changeTokenBalance` pour vérifier le changement de solde ou les `changeTokenBalances` pour un compte multiple. - -La correspondance peut accepter les `numbers`, `strings` et `BigNumbers` comme changement de solde, alors que l'adresse doit être spécifiée en tant que portefeuille ou contrat. - -Écrivons le prochain test : - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Ce qui précède est un test pour un seul portefeuille. - -Et le prochain pour plusieurs portefeuilles : - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -La transaction devrait être passée en tant que rappel (callback) (nous devons vérifier le solde avant l'appel) ou en tant que réponse de transaction. - -## Félicitations {#congratulations} - -**Félicitations ! Vous avez réussi à le faire avec mon tutoriel. Vous avez fait votre premier grand pas vers les tests des contrats intelligents avec Waffle.** - -**Vous pouvez retrouver le code de ce tutoriel [ici](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Pour en apprendre plus sur Waffle, une `documentation` est disponible [ici](https://getwaffle.io).** diff --git a/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 994532ecc8b..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: Bouchonnage dynamique et tests de contrats" -description: Tutoriel Waffle avancé pour utiliser le bouchonnage dynamique et tester les appels de contrat -author: "Daniel Izdebski" -tags: - - "waffle" - - "contrats intelligents" - - "solidity" - - "test" - - "bouchonnage" -skill: intermediate -lang: fr -published: 2020-11-14 ---- - -## À quoi sert ce tutoriel ? {#what-is-this-tutorial-about} - -Dans ce tutoriel, vous apprendrez comment : - -- utiliser le bouchonnage dynamique -- tester les interactions entre contrats intelligents - -Prérequis : - -- vous savez déjà écrire un simple contrat intelligent en `Solidity` -- vous vous débrouillez en `JavaScript` et en `TypeScript` -- vous avez fait d'autres tutoriels `Waffle` ou vous connaissez deux ou trois choses à ce sujet - -## Bouchonnage dynamique {#dynamic-mocking} - -Pourquoi le bouchonnage dynamique est-il utile ? Eh bien, il nous permet de rédiger des tests unitaires plutôt que des tests d'intégration. Qu'est-ce que cela signifie ? Cela signifie que nous n'avons pas à nous soucier des dépendances des contrats intelligents, donc que nous pouvons tous les tester de façon isolée. Laissez-moi vous montrer comment procéder. - -### **1. Projet** {#1-project} - -Avant de commencer, nous avons besoin de préparer un simple projet node.js : - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Commençons par ajouter typescript et les dépendances de test - mocha & chai : - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Maintenant, ajoutons `Waffle` et `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -La structure de votre projet devrait ressembler à ceci : - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Contrat intelligent** {#2-smart-contract} - -Pour démarrer un bouchonnage dynamique, nous avons besoin d'un contrat intelligent avec des dépendances. Ne t'inquiètes pas, nous assurons tes arrières ! - -Voici un contrat intelligent simple écrit en `Solidity` dont le seul but est de vérifier si nous sommes riches. Il utilise un jeton ERC20 pour vérifier si nous avons suffisamment de jetons. Mettez-le dans `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Comme nous voulons utiliser le bouchonnage dynamique, nous n'avons pas besoin de tout l'ERC20, c'est pourquoi nous utilisons l'interface IERC20 avec une seule fonction. - -Il est temps de créer ce contrat ! Pour cela, nous utiliserons le `Waffle`. Tout d'abord, nous allons créer un simple fichier de configuration `waffle.json` qui spécifie les options de compilation. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Nous sommes désormais prêts à construire le contrat avec Waffle : - -```bash -npx waffle -``` - -Facile, n'est-ce pas? Dans le dossier `build/`, deux fichiers correspondant au contrat et à l'interface apparaissent. Nous les utiliserons plus tard pour les tests. - -### **3. Tests** {#3-testing} - -Nous allons créer un fichier appelé `AmIRichAlready.test.ts` pour le test actuel. Tout d'abord, nous devons gérer les importations. Nous en aurons besoin pour plus tard: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Sauf pour les dépendances JS, nous devons importer le contrat et l'interface précédemment créés : - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle utilise `chai` pour le test. Cependant, avant de pouvoir l'utiliser, nous devons injecter les matchers de Waffle dans le chai lui-même : - -```typescript -use(solidity) -``` - -Nous devons implémenter la fonction `beforeEach()` qui réinitialisera l'état du contrat avant chaque test. Réfléchissons d'abord à ce dont nous avons besoin. Pour déployer un contrat, nous avons besoin de deux choses: un wallet et un contrat ERC20 déployé pour le passer comme argument pour le contrat `AmIRichAlready`. - -Premièrement, créons nous un portefeuille: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Ensuite, nous devons déployer un contrat ERC20. Voici la partie délicate - nous n'avons qu'une seule interface. C'est la partie où Waffle vient nous sauver. Waffle a une fonction magique `deployMockContract()` qui crée un contrat en utilisant uniquement le _abi_ de l'interface : - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Maintenant, avec le wallet et l'ERC20 déployé, nous pouvons continuer et déployer le contrat `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Avec tout cela, notre fonction `beforeEach()` est terminée. Pour l'instant, votre fichier `AmIRichAlready.test.ts` devrait ressembler à ceci : - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Écrivons le premier test pour le contrat `AmIRichalready`. De quoi pensez-vous que notre test devrait traiter? Ouais, vous avez raison! Nous devrions vérifier si nous sommes déjà riches :) - -Mais attendez une seconde. Comment notre contrat fictif saura-t-il quelles valeurs retourner? Nous n'avons implémenté aucune logique pour la fonction `balanceOf()`. Là encore, Waffle peut nous aider. Notre contrat fictif a de nouveaux trucs fantaisistes maintenant : - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Avec cette connaissance, nous pouvons enfin écrire notre premier test : - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Décomposons ce test en parties : - -1. Nous avons fixé notre contrat fictif ERC20 pour toujours retourner le solde de 999999 jetons. -2. Vérifiez si la méthode `contract.check()` retourne `false`. - -Nous sommes prêts à allumer la bête : - -![Un test réussi](./test-one.png) - -Alors le test fonctionne, mais... il y a encore des choses à améliorer. La fonction `balanceOf()` retournera toujours 99999. Nous pouvons l'améliorer en spécifiant un portefeuille pour lequel la fonction devrait retourner quelque chose - tout comme un contrat réel : - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Jusqu'à présent, nous avons testé seulement le cas où nous ne sommes pas assez riche. Essayons l'inverse: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Vous exécutez les tests... - -![Deux tests réussis](test-two.png) - -Et voici où tu en es! Notre contrat semble fonctionner comme prévu :) - -## Test des appels de contrat {#testing-contract-calls} - -Résumons ce qui a été fait jusqu'à présent. Nous avons testé la fonctionnalité de notre contrat `AmIRichalready` et il semble qu'il fonctionne correctement. Cela signifie que nous avons terminé, n'est-ce pas? Pas exactement ! Waffle nous permet de tester encore plus notre contrat. Mais comment exactement ? Eh bien, dans l'arsenal de Waffle, il y a une correspondance entre `calledOnContract()` et `calledOnContractWith()`. Cela va nous permettre de vérifier si notre contrat a appelé le contrat fictif ERC20. Voici un test de base avec l'une de ces correspondance: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Nous pouvons aller encore plus loin et améliorer ce test avec l'autre matcher dont nous vous avons parlé: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Vérifions si les tests sont corrects : - -![Trois tests réussis](test-three.png) - -Super, tous les tests sont verts. - -Tester des appels de contrats avec Waffle est super facile. Et voici la meilleure partie. Ces matchers fonctionnent à la fois avec des contrats normaux et fictifs ! C'est parce que Waffle enregistre et filtre les appels EVM plutôt que d'injecter du code, comme c'est le cas des bibliothèques de test populaires pour d'autres technologies. - -## La fin {#the-finish-line} - -Félicitations ! Maintenant vous savez comment utiliser Waffle pour tester dynamiquement les appels de contrats et les contrats fictifs. Il y a beaucoup plus de fonctionnalités intéressantes à découvrir. Je recommande de plonger dans la documentation de Waffle. - -La documentation Waffle est disponible [here](https://ethereum-waffle.readthedocs.io/). - -Le code source de ce tutoriel est disponible [ici](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Voici d'autres tutoriels qui pourraient vous intéresser : - -- [Tester des contrats intelligents avec Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index b4715e9ca5e..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: 'Tutoriel pour "dire bonjour au monde" avec hardhat et ethers' -description: Réalisez votre premier projet Waffle avec hardhat et ethers.js -author: "MiZiet" -tags: - - "waffle" - - "contrats intelligents" - - "solidité" - - "test" - - "hardhat" - - "ethers.js" -skill: beginner -lang: fr -published: 2020-10-16 ---- - -Dans ce tutoriel [Waffle](https://ethereum-waffle.readthedocs.io), nous apprendrons comment créer un simple contrat intelligent "Hello world", en utilisant [hardhat](https://hardhat.org/) et [ethers.js](https://docs.ethers.io/v5/). Ensuite nous apprendrons conmment ajouter une nouvelle fonctionnalité à notre contrat intelligent et comment la tester avec « Waffle ». - -Commençons par créer un nouveau projet : - -```bash -yarn init -``` - -ou - -```bash -npm init -``` - -et l'installation des paquets nécessaires : - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -ou - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -L'étape suivante est la création d'un projet hardhat basique en exécutant `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Bienvenue dans Hardhat v2.0.3 👷‍ - -? Que voulez vous faire ? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Sélectionnez `Create a sample project` - -Notre structure de projet devrait ressembler à ceci : - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributs -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Maintenant, parlons de certains de ces fichiers : {#now-lets-talk} - -- Greeter.sol - notre contrat intelligent écrit en solidity ; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Notre contrat intelligent peut être divisé en trois parties : - -1. constructeur - où nous déclarons une variable de type string appelée `greeting`, -2. function greet - une fonction qui retournera la valeur `greeting` lorsqu'elle est appelée, -3. function setGreeting - une fonction qui nous permet de changer la valeur `greeting`. - -- sample-test.js - notre fichier de tests - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### La prochaîne étape consiste à compiler notre contrat et à exécuter nos tests : {#compiling-and-testing} - -Les tests Waffle utilisent Mocha (un framework de test) avec Chai (une bibliothèque d'assertions). Tout ce que vous avez à faire est d'exécuter `npx hardhat test` et d'attendre que le message suivant apparaisse. - -```bash -✓ Doit renvoyer le nouveau message de bienvenue une fois qu'il a changé -``` - -### Tout semble bien pour l'instant, ajoutons une certaine complexité à notre projet {#adding-complexity} - -Imaginez une situation où quelqu'un ajoute une chaîne vide comme un salut. Ce ne serait pas un accueil chaleureux, n'est-ce pas ? -Veillons à ce que cela ne se produise pas : - -Nous voulons utiliser la version de solidity `revert` lorsque quelqu'un passe une chaîne vide. Une bonne chose est que nous pouvons facilement tester cette fonctionnalité avec la correspondance chai de Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - wait greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Il semblerait que notre nouveau test n'ait pas réussi : - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implémentons cette fonctionnalité dans notre contrat intelligent : - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Maintenant, notre fonction setGreeting ressemble à ceci : - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Exécutons les tests à nouveau : - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Félicitations ! Vous y êtes arrivé :) - -### Conclusion {#conclusion} - -Nous avons réalisé un projet simple avec Waffle, Hardhat et ethers.js. Nous avons appris comment mettre en place un projet, ajouter un test et implémenter de nouvelles fonctionnalités. - -Pour plus d'excellents correspondants chai pour tester vos contrats intelligents, consultez la [documentation officielle de Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 13ee9082e20..00000000000 --- a/public/content/translations/fr/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Test d'un contrat intelligent simple avec la bibliothèque Waffle -description: Tutoriel pour débutants -author: Ewa Kowalska -tags: - - "contrats intelligents" - - "solidity" - - "Waffle" - - "test" -skill: beginner -lang: fr -published: 2021-02-26 ---- - -## Dans ce tutoriel, vous apprendrez à {#in-this-tutorial-youll-learn-how-to} - -- Tester les modifications du solde du portefeuille -- Tester l'émission d'événements avec les arguments spécifiés -- Confirmer qu'une transaction a été annulée - -## Hypothèses {#assumptions} - -- Vous pouvez créer un nouveau projet JavaScript ou TypeScript -- Vous avez une expérience de base en matière de tests JavaScript -- Vous avez utilisé des gestionnaires de paquets comme yarn ou npm -- Vous possédez des connaissances de base en matière de contrats intelligents et de Solidity - -## Premiers pas {#getting-started} - -Le tutoriel décrit l'installation et l'exécution du test en utilisant yarn, mais il n'y a pas de problème si vous préférez npm - je fournirai les références appropriées à la documentation officielle de Waffle.[](https://ethereum-waffle.readthedocs.io/en/latest/index.html) - -### Installer les dépendances {#install-dependencies} - -[Ajoutez](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) dépendances ethereum-waffle et typescript aux dépendances de développement de votre projet. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -### Exemple de contrat intelligent {#example-smart-contract} - -Au cours du tutoriel, nous allons travailler sur un exemple de contrat intelligent simple - EtherSplitter. Il ne fait pas grand-chose à part permettre à quelqu'un d'envoyer des wei et de les répartir équitablement entre deux destinataires prédéfinis. La fonction de séparation nécessite que le nombre de wei soit pair, sinon elle s'inverse. Pour les deux destinataires, il effectue un transfert de wei suivi de l'émission de l'événement Transfert. - -Placez le fragment de code EtherSplitter dans `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -### Compiler le contrat {#compile-the-contract} - -Pour [compiler](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) le contrat, ajoutez l'entrée suivante au fichier package.json : - -```json -"scripts": { - "build": "waffle" - } -``` - -Ensuite, créez un fichier de configuration avec Waffle, dans le répertoire principal des projets, - `waffle.json` - puis collez-y la configuration suivante : - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Exécutez `yarn build`. Cela fera apparaître le dossier `build` avec le contrat compilé EtherSplitter au format JSON. - -### Configuration du test {#test-setup} - -Tester avec Waffle nécessite d'utiliser des correspondances Chai et Mocha, vous devez donc [les ajouter](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) à votre projet. Lancez la mise à jour de votre paquet package.json, et ajoutez le `texte`d'entrée, dans la partie modèle: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Si vous voulez [faire](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) vos propres tests, exécutez juste le `yarn test` . - -## Tests {#testing} - -Maintenant, créez le dossier `test` et créez le nouveau fichier `test\EtherSplitter.test.ts`. Copiez le fragment ci-dessous et collez-le dans notre fichier de test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -Quelques mots avant de commencer. Le fournisseur de services, `MockProvider`, propose une version fictive de la blockchain. Il fournit également des portefeuilles fictifs, qui serviront de base pour tester le contrat intelligent EtherSplitter. Nous pouvons obtenir jusqu'à dix portefeuilles en appelant la méthode `getWallets()` sur le fournisseur. Dans l'exemple, nous avons trois portefeuilles - pour l'expéditeur et pour deux destinataires. - -Ensuite, nous déclarons une variable appelée « splitter » - c'est notre contrat fictif EtherSpliter. Il est créé avant chaque exécution d'un test unique par la méthode `deployContract`. Cette méthode simule le déploiement d'un contrat à partir du portefeuille transmis en tant que premier paramètre (le portefeuille de l'expéditeur dans notre cas). Le deuxième paramètre est l'ABI et le bytecode du contrat testé - nous transmettons le fichier json du contrat EtherSplitter compilé à partir du répertoire `build`. Le troisième paramètre est un tableau contenant les arguments du constructeur du contrat qui, dans notre cas, sont les deux adresses des destinataires. - -### changeBalances {#changebalances} - -Tout d'abord, nous vérifierons si la méthode fractionnée modifie réellement les soldes des portefeuilles des destinataires. Si nous divisons 50 wei du compte des expéditeurs, nous nous attendons à ce que les soldes des deux destinataires augmentent de 25 wei. Nous utiliserons la correspondance `changeBalances` de Waffle: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Comme premier paramètre de la correspondance, nous transmettons un tableau de portefeuilles de destinataires, et comme deuxième, un tableau d'augmentations attendues sur les comptes correspondants. Si nous voulions vérifier le solde d'un portefeuille spécifique, nous pourrions également utiliser la correspondance `changeBalance` , qui ne nécessite pas de transmettre des tableaux, comme dans l'exemple ci-dessous: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Notez que dans les deux cas de `changeBalance` et `changeBalances`, nous transmettons la fonction de séparation comme callback car le correspondant a besoin d'accéder à l'état des balances avant et après l'appel. - -Nous allons ensuite déterminer si l'événement Transfert a été émis après chaque transfert de wei. Nous allons passer à une autre correspondance de Waffle : - -### Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -La correspondance `emit` nous permet de vérifier si un contrat a émis un événement en appelant une méthode. En tant que paramètres pour la corrrespondance `emit`, nous fournissons le contrat fictif que nous prévoyons pour émettre l'événement, ainsi que le nom de cet événement. Dans notre cas, le contrat fictif est `splitter` et le nom de l'événement `Transfer`. Nous pouvons également vérifier les valeurs précises des arguments avec lesquels l'événement a été émis - nous transmettons autant d'arguments au `withArgs` correspondant, comme le prévoit notre déclaration d'événement. Dans le cas du contrat EtherSpliter, nous passons les adresses de l'expéditeur et du destinataire avec le montant en wei transféré. - -### revertedWith {#revertedwith} - -Comme dernier exemple, nous allons vérifier si la transaction a été annulée en cas de nombre impair de wei. Nous allons utiliser la correspondance `revertedWith` : - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -Le test, s'il est accepté, nous assurera que la transaction a bien été annulée. Cependant, il doit également y avoir une correspondance exacte entre les messages que nous avons passés dans la déclaration `require` et le message attendu dans `revertedWith`. Si nous revenons au code du contrat EtherSpliter, dans la déclaration `require` pour le montant wei, nous fournissons le message: "Uneven wei amount not allowed". Cela correspond au message que nous attendons dans notre test. Si elles n'étaient pas égales, le test échouerait. - -## Félicitations ! {#congratulations} - -Vous avez fait votre premier (grand) pas vers les tests des contrats intelligents avec Waffle ! diff --git a/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 55441fcb3ce..00000000000 --- a/public/content/translations/id/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: Menguji token ERC-20 dengan Waffle -description: Pelajari cara menguji kontrak pintar Solidity dan menggunakan matcher kontrak pintar dengan Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "erc-20" -skill: intermediate -lang: id -published: 2020-10-16 ---- - -Pada tutorial ini, Anda akan belajar cara: - -- Menulis tes untuk kontrak pintar dengan Waffle -- Menggunakan beberapa matcher populer untuk menguji kontrak pintar dengan Waffle - -Asumsi: - -- Anda dapat menguasai penggunaan terminal, -- Anda dapat membuat proyek `JavaScript` baru, -- Anda telah menulis beberapa baris kode `Solidity`, -- Anda telah menulis beberapa tes dalam `JavaScript`, -- Anda telah menggunakan `yarn` atau `npm`, penginstal paket JavaScript. - -Sekali lagi, jika salah satu dari asumsi ini tidak benar, atau Anda tidak berencana untuk membuat kembali kode dalam artikel ini, Anda kemungkinan masih dapat mengikuti penjelasannya dengan baik. - -## Beberapa kata tentang Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) adalah pustaka yang paling canggih untuk penulisan dan pengujian kontrak pintar. - -Berfungsi dengan [API JavaScript](/developers/docs/apis/javascript/) ethers-js. - -Anda dapat membaca detail selengkapnya di [dokumentasi Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial cepat {#the-quick-tutorial} - -Pertama-tama, buat proyek `JavaScript` atau `TypeScript` baru ( Saya akan menggunakan `TS`, tetapi jika Anda menggunakan `JS` itu tidak jadi masalah ) : - -Itu akan tampak seperti ini: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Langkah #1: Instal waffle dalam proyek Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Untuk memulai, instal `ethereum-waffle`. Dalam tutorial ini, saya akan menggunakan `yarn`, sehingga untuk menginstal `ethereum-waffle` jalankan: - -```bash - yarn add --dev ethereum-waffle -``` - -## Langkah #2: Tulis kontrak pintar [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -Dalam tutorial ini, saya akan menggunakan token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) dari [OpenZeppelin](https://openzeppelin.com). - -Jadi, tambahkan `OpenZeppelin` dengan menginstalnya dengan menggunakan `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Lalu buat kontrak `BasicToken.sol` di direktori `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Kelas percontohan - sebuah kelas tiruan yang menggunakan pengantaran dari ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Langkah #3: Kompilasikan kontrak pintar Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Untuk mengompilasi kontrak pintar Anda, tambahkan entri berikut ke dalam `package.json` proyek Anda: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Selain itu, tambahkan file `waffle.json` dalam direktori utama proyek Anda. - -Contoh konfigurasi `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Anda dapat membaca lebih banyak tentang konfigurasi Waffle [di sini](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Lalu cukup jalankan `yarn build` untuk mengompilasi kontrak pintar Anda. - -Anda akan melihat bahwa Waffle mengompilasi kontrak Anda dan menempatkan output JSON yang dihasilkan di dalam directori `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## Langkah #4: Uji kontrak pintar Anda [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Langkah #4.1 Instal dependensi yang diperlukan [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Setelah kita telah berhasil menulis sebuah Kontrak Pintar, kita dapat mengujinya. Kita akan menggunakan `Waffle` untuk melakukannya. - -Tes dalam `Waffle` ditulis dengan menggunakan `Mocha` bersama dengan `Chai`. Kita dapat menggunakan lingkungan pengujian berbeda, tetapi matcher `Waffle` hanya berfungsi dengan `Chai`. - -Jadi, kita perlu menambahkan `Chai` ke dependensi kita: - -```bash - yarn add --dev mocha chai -``` - -### Langkah #4.2 Buat file uji [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Untuk menulis tes, kita perlu membuat file `BasicToken.test.ts` dalam direktori tes kita. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Jadi, kita menggunakan metode `deployContract` dari `Waffle` untuk menyebarkan token kita. Sebagai argumen, kita harus meneruskan `dompet`, file json terkompilasi dari kontrak kita, dan saldo default. - -`Waffle` juga memungkinkan kita membuat `dompet`, yang sangat memudahkan dalam menyebarkan kontrak. - -Anda dapat membaca selengkapnya tentang `dompet` [di sini](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) dan Anda dapat membaca selengkapnya tentang fungsi penggunaan [di sini](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Mari menulis sebuah tes sederhana untuk memeriksa saldo dompet kita. Karena kita mengirimkan senilai 1000 pada saat penggunaan kontrak, saldo dompet kita harus bernilai 1000 token, yang dapat kita periksa pada tes pertama. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Untuk menjalankan tes gunakan `yarn test` - -### Langkah #4.3 Memancarkan aksi [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -Dalam tutorial ini, saya ingin menunjukkan kepada Anda matcher yang paling berguna dari `Waffle`, jadi mari kita mulai dengan yang pertama. - -`Waffle` memungkinkan Anda menguji aksi mana yang dipancarkan. - -Dalam tutorial ini, saya akan menguji metode `transfer` kontrak kita. - -Dalam tes ini, saya akan membuat sebuah transfer dari satu dompet ke dompet lainnya dan memeriksa apakah aksi `Transfer` dipanggil. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Selain itu, keunggulan besar dari matcher ini adalah kita dapat memeriksa di argumen mana aksi ini dipanggil dengan menambahkan `withArgs` ke dalam tes kita. - -Ini akan memungkinkan kita memastikan bahwa fungsi kita dipanggil dengan benar! - -### Langkah #4.4 Balikkan dengan message [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` memungkinkan kita menguji dengan message mana itu dibalikkan. - -Kita akan menggunakan matcher `revertedWith` dalam tes kita untuk mengujinya. - -Kita dapat menulis sebuah tes yang dalamnya kita akan melakukan transfer dengan jumlah lebih besar dari yang kita miliki dalam dompet kita. Dan kemudian kita akan memeriksa apakah transaksinya dibalikkan dengan message yang tepat! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Langkah #4.5 Ubah saldo token [Tautkan ke dokumen](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` memungkinkan kita memeriksa perubahan dalam saldo dompet! - -Kita dapat menggunakan matcher `changeTokenBalance` untuk memeriksa perubahan saldo atau `changeTokenBalances` untuk beberapa akun. - -Matcher dapat menerima `numbers`, `strings` dan `BigNumbers` sebagai perubahan saldo, sedangkan alamatnya akan ditentukan sebagai dompet atau kontrak. - -Mari menulis tes berikutnya: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Tes di atas merupakan tes untuk sebuah dompet tunggal. - -Dan yang berikut ini untuk beberapa dompet: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -Transaksinya diharapkan untuk diteruskan sebagai callback (kita perlu memeriksa saldo sebeleum pemanggilan ini) atau sebagai respon transaksi. - -## Selamat {#congratulations} - -**Selamat! Anda telah menyelesaikan tutorial saya. Anda telah mengambil langkah besar pertama Anda dalam menguji kontrak pintar dengan Waffle.** - -**Kode dari tutorial ini dapat Anda temukan [di sini](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Lebih banyak dokumentasi tentang `Waffle` tersedia [di sini](https://getwaffle.io).** diff --git a/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 653f0ca5d46..00000000000 --- a/public/content/translations/id/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: Mocking dinamis dan percobaan memanggil kontrak pintar" -description: Tutorial tingkat lanjut Waffle untuk menggunakan mocking dinamis dan percobaan memanggil kontrak -author: "Daniel Izdebski" -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "mocking" -skill: intermediate -lang: id -published: 2020-11-14 ---- - -## Apa yang akan di pelajari pada tutorial ini? {#what-is-this-tutorial-about} - -Pada tutorial ini, Anda akan belajar cara: - -- menggunakan mocking dinamis -- menguji interaksi antara kontrak pintar - -Asumsi: - -- Anda telah mengetahui bagaimana cara menulis kontrak pintar sederhana dalam `Solidity` -- Anda terbiasa dengan `JavaScript` dan `TypeScript` -- Anda telah menyelesaikan tutorial `Waffle` lainnya atau mengetahui beberapa hal tentangnya - -## Mocking dinamis {#dynamic-mocking} - -Mengapa mocking dinamis sangat berguna? Baiklah, hal ini mengizinkan kita menulis tes unit ketimbang tes yang terintegrasi. Apa maksudnya? Hal ini berarti bahwa kita tidak perlu khawatir tentang dependensi kontrak pintar, sehingga kita bisa menguji semuanya secara terisolasi. Saya akan menunjukan bagaimana cara Anda melakukannya. - -### **1. Proyek** {#1-project} - -Sebelum memulai, kita perlu menyiapkan proyek node.js sederhana: - -```bash -$ mkdir dynamic-mocking -$ cd dynamic-mocking -$ mkdir contracts src - -$ yarn init -# or if you're using npm -$ npm init -``` - -Mari kita mulai dengan menambah typescript dan menguji dependensi - mocha dan chai: - -```bash -$ yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# atau jika anda menggunakan npm -$ npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Sekarang mari tambahkan `Waffle` dan `ether`: - -```bash -$ yarn add --dev ethereum-waffle ethers -# atau jika anda menggunakan npm -$ npm install ethereum-waffle ethers --save-dev -``` - -Struktur proyek Anda seharusnya terlihat seperti ini: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Kontrak pintar** {#2-smart-contract} - -Untuk memulai mocking dinamis, kita membutuhkan kontrak pintar dengan dependensi. Tenang, saya akan membantu! - -Berikut adalah kontrak pintar sederhana yang ditulis dalam `Solidity` yang tujuannya hanya memeriksa apakah kita kaya. Kontrak pintar ini menggunakan token ERC20 untuk memeriksa apakah kita memiliki token yang cukup. Letakan pada `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Karena kita mau menggunakan mocking dinamis, kita tidak memerlukan seluruh ERC20, itulah mengapa kita menggunakan antarmuka IERC20 dengan hanya satu fungsi. - -Saatnya membuat kontrak ini! Untuk itu, kita akan menggunakan `Waffle`. Pertama, kita akan membuat file konfigurasi `waffle.json` sederhana yang menentukan pilihan kompilasi. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Sekarang, kita sudah siap untuk membuat kontrak menggunakan Waffle: - -```bash -$ npx waffle -``` - -Mudah, bukan? Dalam folder `build/`, dua file sesuai dengan kontrak dan antar mukanya muncul. Kita akan menggunakannya nanti untuk percobaan. - -### **3. Pengujian** {#3-testing} - -Mari kita buat file bernama `AmIRichAlready.test.ts` untuk tes yang sebenarnya. Pertama, kita harus menangani hasil impor. Kita akan membutuhkannya nanti: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Kecuali untuk dependensi JS, kita harus mengimpor kontrak dan antar muka yang kita bangun: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle menggunakan `chai` untuk pengujian. Namun, sebelum kita menggunakannya, kita harus menginjeksi matcher Waffle kedalam chai: - -```typescript -use(solidity) -``` - -Kita harus mengimplementasikan fungsi `beforeEach()` yang akan mengatur ulang state kontrak sebelum setiap tes dimulai. Pertama-tama mari kita pikirkan apa yang kita butuhkan untuk itu. Untuk menggunakan kontrak, kita membutuhkan dua hal: dompet dan kontrak ERC20 yang digunakan untuk meneruskannya sebagai argumen kontrak `AmIRichAlready`. - -Pertama, kita buat dompetnya: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Selanjutnya, kita harus menggunakan kontrak ERC20. Ini bagian sulitnya - kita hanya memiliki satu antarmuka. Di sinilah peran di mana Waffle datang menyelamatkan kita. Waffle memiliki fungsi `deployMockContract()` ajaib yang membuat kontrak dengan hanya menggunakan _abi_ dari antarmuka: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Sekarang dengan dompet maupun ERC20 yang digunakan, kita akan lanjutkan dan menggunakan kontrak `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Secara keseluruhan, fungsi `beforeEach()` kita telah selesai. Sejauh ini file `AmIRichAlready.test.ts` Anda seharusnya telihat seperti ini: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Mari kita tulis tes pertama ke kontrak `AmIRichAlready`. Menurut Anda, tentang apa seharusnya tes kita? Ya, Anda benar! Kita harus memeriksa apakah kita sudah kaya :) - -Tapi tunggu dulu. Bagaimana kontrak mocked kita tahu nilai apa yang dikembalikan? Kita belum mengimplementasikan logika apa pun untuk fungsi `balanceOf()`. Sekali lagi, Waffle bisa membantu kita di sini. Kontrak mocked kita memiliki hal baru yang menarik sekarang: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Dengan pengetahuan ini, akhirnya kita bisa menulis tes pertama kita: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Mari kita pecahkan tes ini ke dalam bagian-bagian: - -1. Kita atur kontrak mock ERC20 kita untuk selalu mengembalikan saldo 999999 token. -2. Periksa apakah metode `contract.check()` mengembalikan nilai `false`. - -Kita siap untuk menyalakannya: - -![Satu ujian lulus](./test-one.png) - -Jadi testnya bekerja, namun... masih ada sedikit ruang untuk peningkatan. Fungsi `balanceOf()` akan selalu mengembalikan 99999. Kita bisa meningkatkannya dengan menentukan dompet yang ke mana fungsinya harus mengembalikan sesuatu - sama seperti kontrak sungguhan: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Sejauh ini, kita hanya mencoba kasus di mana kita tidak cukup kaya. Mari kita coba kebalikannya: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Anda jalankan tesnya... - -![Dua ujian lulus](test-two.png) - -....dan ini dia! Kontrak kita tampak berjalan sebagaimana mestinya :) - -## Menguji pemanggilan kontrak {#testing-contract-calls} - -Mari kita ringkas apa yang telah kita lakukan sejauh ini. Kita telah menguji fungsionalitas kontrak `AmIRichAlready` kita dan tampaknya bekerja dengan benar. Artinya, kita telah selesai, bukan? Belum selesai! Waffle memungkinkan kita menguji kontrak bahkan lebih jauh lagi. Tapi, bagaimana persisnya? Dalam gudang senjata Waffle, ada matcher `calledOnContract()` dan `calledOnContractWith()`. Mereka akan memungkinkan kita memeriksa apakah kontrak kita memanggil kontrak mock ERC20. Berikut adalah tes dasarnya dengan salah satu matcher ini: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Kita bahkan bisa melangkah lebih jauh dan meningkatkan tes ini dengan matcher lain yang saya sebutkan sebelumnya: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Mari kita periksa apakah tesnya benar: - -![Tiga ujian lulus](test-three.png) - -Hebat, semua test berwarna hijau. - -Menguji pemanggilan kontrak dengan Waffle sangatlah mudah. Dan inilah bagian terbaiknya. Matcher ini bekerja baik dalam kontrak normal dan mocked! Itu karena Waffle mencatat dan menyaring pemanggilan EVM ketimbang menginjeksi kode, seperti dalam kasus pustaka pengujian populer untuk teknologi lainnya. - -## Garis Akhir {#the-finish-line} - -Selamat! Sekarang Anda tahu cara menggunakan Waffle untuk menguji pemanggilan kontrak dan kontrak mock secara dinamis. Ada fitur yang jauh lebih menarik untuk ditemukan. Saya menyarankan menyelam ke dalam dokumentasi Waffle. - -Dokumentasi Waffle tersedia [di sini](https://ethereum-waffle.readthedocs.io/). - -Sumber kode untuk tutorial ini bisa ditemukan [di sini](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Tutorial yang mungkin juga Anda minati: - -- [Menguji kontrak pintar dengan Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 803f0a465a0..00000000000 --- a/public/content/translations/id/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Tutorial Waffle hello world menggunakan hardhat dan ether" -description: Buat proyek Waffle pertama Anda dengan hardhat dan ethers.js -author: "MiZiet" -tags: - - "waffle" - - "kontrak pintar" - - "solidity" - - "pengujian" - - "hardhat" - - "ethers.js" -skill: beginner -lang: id -published: 2020-10-16 ---- - -Dalam tutorial [Waffle](https://ethereum-waffle.readthedocs.io) ini, kita akan belajar cara menyiapkan proyek kontrak pintar "Hello world" yang sederhana, menggunakan [hardhat](https://hardhat.org/) dan [ethers.js](https://docs.ethers.io/v5/). Kemudian kita akan belajar cara menambahkan fungsionalitas baru ke kontrak pintar kita dan cara mengujinya dengan Waffle. - -Mari kita mulai dengan membuat proyek baru: - -```bash -yarn init -``` - -atau - -```bash -npm init -``` - -dan menginstal paket yang diperlukan: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -atau - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Langkah selanjutnya adalah membuat proyek hardhat percontohan dengan menjalankan `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Selamat datang di HardHat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Pilih `Buat proyek sampel` - -Struktur proyek kita seharusnya terlihat seperti ini: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributs -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Sekarang mari kita bicara tentang beberapa file ini: {#now-lets-talk} - -- Greeter.sol - kontrak pintar kita yang ditulis dalam solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Kontrak pintar kita dapat dibagi menjadi tiga bagian: - -1. constructor - tempat kami mendeklarasikan variabel tipe string yang disebut `greeting`, -2. function greet - sebuah fungsi yang akan mengembalikan `greeting` saat dipanggil, -3. function setGreeting - fungsi yang memungkinkan kita mengubah nilai `greeting`. - -- sample-test.js - file tes kita - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Langkah selanjutnya terdiri dari mengompilasi kontrak kita dan menjalankan pengujian: {#compiling-and-testing} - -Pengujian wafel menggunakan Mocha (kerangka pengujian) dengan Chai (pustaka assertion). Yang harus Anda lakukan adalah menjalankan `npx hardhat test` dan menunggu pesan berikut muncul. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Semuanya terlihat bagus sejauh ini, mari tambahkan lebih banyak kerumitan pada proyek kita {#adding-complexity} - -Bayangkan suatu situasi ketika seseorang menambahkan string kosong sebagai salam. Ini bukan sapaan yang hangat, bukan? -Mari kita pastikan itu tidak terjadi: - -Kita ingin menggunakan `revert` solidity ketika seseorang melewati string kosong. Hal baiknya adalah kita bisa dengan mudah menguji fungsionalitas ini dengan `to.be.revertedWith ()` matcher chai Waffle. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Sepertinya tes baru kita tidak lulus: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Mari kita terapkan fungsi ini ke dalam kontrak pintar kita: - -```solidity -require(bytes(_greeting).length > 0, "Salam tidak boleh kosong"); -``` - -Sekarang, fungsi setGreeting kita terlihat seperti ini: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Mari kita jalankan tes lagi: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Selamat! Anda berhasil :) - -### Kesimpulan {#conclusion} - -Kita membuat proyek sederhana dengan Waffle, Hardhat, dan eters.js. Kita mempelajari cara menyiapkan proyek, menambahkan pengujian, dan mengimplementasikan fungsionalitas baru. - -Untuk chai matcher yang lebih hebat untuk menguji kontrak pintar Anda, lihat [dokumen resmi Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 8ccacffadef..00000000000 --- a/public/content/translations/it/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: Testare i token ERC-20 con Waffle -description: Scopri come testare i contratti intelligenti di Solidity e usa gli abbinatori di contratti intelligenti con Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "Smart Contract" - - "Solidity" - - "test" - - "erc-20" -skill: intermediate -lang: it -published: 2020-10-16 ---- - -In questo tutorial imparerai come: - -- Scrivere test per i contratti intelligenti con Waffle -- Usare alcuni abbinatori popolari per testare i contratti intelligenti con Waffle - -Premesse: - -- sai muoverti in un terminale, -- sai creare un nuovo progetto `JavaScript`, -- hai scritto alcune righe di codice in `Solidity`, -- hai scritto qualche test in `JavaScript`, -- hai usato `yarn` o `npm`, installatore di pacchetti di JavaScript. - -Ancora, se alcune di queste premesse sono false o non desideri riprodurre il codice in questo articolo, puoi probabilmente seguirlo ancora e senza problemi. - -## Qualche parola su Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) è la libreria più avanzata per scrivere e testare i contratti intelligenti. - -Opera con ethers-js dell'[API di JavaScript](/developers/docs/apis/javascript/). - -Puoi leggere maggiori dettagli nella [documentazione di Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## Tutorial rapido {#the-quick-tutorial} - -Per prima cosa, crea un nuovo progetto `JavaScript` o `TypeScript` (Userò `TS`, ma se usi `JS` non è un problema ): - -Qualcosa del genere: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Fase #1: Installa waffle nel tuo progetto [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Per iniziare, installa `ethereum-waffle`. In questo tutorial userò `yarn`, quindi per installare `ethereum-waffle`, esegui: - -```bash - yarn add --dev ethereum-waffle -``` - -## Fase #2: Scrivere un contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -In questo tutorial, userò un token [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) da [OpenZeppelin](https://openzeppelin.com). - -Quindi, aggiungi `OpenZeppelin` installandolo con `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Poi, crea il contratto `BasicToken.sol` nella cartella `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Fase #3: Compila il tuo contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Per compilare il tuo contratto intelligente, aggiungi la seguente voce nel `package.json` del tuo progetto: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Inoltre, aggiungi il file `waffle.json` nella cartella principale del tuo progetto. - -Un esempio della configurazione di `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Puoi leggere di più sulla configurazione di Waffle [qui](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Poi basta eseguire `yarn build` per compilare il tuo contratto intelligente. - -Dovresti vedere che Waffle ha compilato il tuo contratto e posizionato l'output JSON risultante nella cartella `build`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## Fase #4: Testa il tuo contratto intelligente [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Fase #4.1 Installa le dipendenze necessaria [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Dopo aver autorizzato con successo un contratto intelligente, possiamo testarlo. Useremo `Waffle` per farlo. - -I test con `Waffle` sono scritti usando `Mocha` insieme a `Chai`. Possiamo usare un ambiente di test diverso, ma gli abbinatori di `Waffle` funzionano solo con `Chai`. - -Quindi, dobbiamo aggiungere `Chai` alle nostre dipendenze: - -```bash - yarn add --dev mocha chai -``` - -### Fase #4.2 Crea il file di test [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Per scrivere il nostro test dobbiamo creare il file `BasicToken.test.ts` nella nostra cartella di prova. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Quindi, usiamo il metodo `deployContract` di `Waffle` per distribuire il nostro token. Come argomenti dovremmo passare `wallet`, il file json compilato del nostro contratto e il saldo predefinito. - -`Waffle` ci consente inoltre di creare un `wallet`, il che rende davvero semplice la distribuzione di un contratto. - -Puoi leggere di più sul `wallet` [qui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) e puoi leggere di più sulla funzione di distribuzione [qui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Scriviamo un test semplice per controllare il saldo del nostro portafoglio. Poiché abbiamo inviato il valore 1000 durante la distribuzione del nostro contratto, il saldo del nostro portafoglio dev'essere 1000 token, che possiamo verificare nel primo test. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Per eseguire il test, usa `yarn test` - -### Fase #4.3 Emettere eventi [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -In questo tutorial, voglio mostrarti gli abbinatori di `Waffle` più utili, iniziamo con il primo. - -`Waffle` ci consente di testare che eventi sono emessi. - -In questo tutorial, testerò il metodo `transfer` del nostro contratto. - -In questo test, effettuerò un trasferimento da un portafoglio a un altro e controllerò se l'evento `Transfer` è stato chiamato. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Inoltre, un grande vantaggio di questo abbinatore è che possiamo controllare quali argomenti sono stati chiamati da quest'evento aggiungendo `withArgs` al nostro test. - -Questo ci consentirà di esser sicuri che la nostra funzione stia venendo chiamata correttamente! - -### Fase #4.4 Ripristino con il messaggio [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` ci consente di testare con che messaggio è stato ripristinato. - -Useremo l'abbinatore `revertedWith` nel nostro test per controllarlo. - -Possiamo scrivere un test in cui eseguiremo un trasferimento per un importo maggiore di quanto abbiamo nel nostro portafoglio. E poi controlleremo se la transazione è tornata con il messaggio esatto! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Fase #4.5 Cambiamento del saldo dei token [Link alla documentazione](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` ci consente di verificare le modifiche ai saldi dei portafogli! - -Possiamo usare l'abbinatore `changeTokenBalance` per controllare il cambiamento del saldo o `changeTokenBalances` per un conto multiplo. - -L'abbinatore può accettare `numbers`, `strings` e `BigNumbers` come cambiamento di un saldo, mentre l'indirizzo dovrebbe esser specificato come un portafoglio o un contratto. - -Scriviamo il prossimo test: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Quanto sopra è un test per un singolo portafoglio. - -E il successivo per più portafogli: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -La transazione dovrebbe passare come callback (dobbiamo controllare il saldo prima della chiamata) o come una risposta della transazione. - -## Congratulazioni {#congratulations} - -**Congratulazioni! Hai concluso il mio tutorial. Hai fatto il tuo primo grande passo verso i contratti intelligenti con Waffle.** - -**Il codice da questo tutorial si può trovare [qui](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Altra documentazione su `Waffle` è disponibile [qui](https://getwaffle.io).** diff --git a/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 676f647e349..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: simulazioni dinamiche e test delle chiamate del contratto" -description: Tutorial avanzato su Waffle per usare la simulazione dinamica e testare le chiamate di contratto -author: "Daniel Izdebski" -tags: - - "waffle" - - "smart contract" - - "Solidity" - - "test" - - "simulazione" -skill: intermediate -lang: it -published: 2020-11-14 ---- - -## A cosa serve questo tutorial? {#what-is-this-tutorial-about} - -In questo tutorial imparerai come: - -- usare la simulazione dinamica -- testare interazioni tra Smart Contract - -Premesse: - -- sai già come scrivere un semplice Smart Contract in `Solidity` -- sai utilizzare `JavaScript` e `TypeScript` -- hai seguito altri tutorial di `Waffle<` o ne sai già qualcosa - -## Simulazione dinamica {#dynamic-mocking} - -Perché la simulazione dinamica è utile? Ci consente di scrivere unit test anziché test di integrazione. Cosa significa? Che non dobbiamo preoccuparci delle dipendenze tra gli Smart Contract, dunque possiamo testarli tutti in completo isolamento. Vediamo come. - -### **1. Progetto** {#1-project} - -Prima di iniziare dobbiamo preparare un semplice progetto node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Iniziamo aggiungendo dipendenze typescript e di test: mocha e chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Ora aggiungiamo `Waffle` e `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -La struttura del progetto sarà ora simile a: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Smart Contract** {#2-smart-contract} - -Per avviare la simulazione dinamica, serve uno Smart Contract con dipendenze. Nessun problema. - -Ecco un semplice Smart Contract scritto in `Solidity` con il solo scopo di controllare se siamo ricchi. Usa il token ERC20 per verificare se abbiamo abbastanza token. Inseriscilo in `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Poiché vogliamo usare la simulazione dinamica, non ci serve tutto ERC20, quindi usiamo l'interfaccia IERC20 con una sola funzione. - -È ora di creare questo contratto. Per questo useremo `Waffle`. Prima, creeremo un semplice file di configurazione `waffle.json` che specifichi le opzioni di compilazione. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Ora siamo pronti a creare il contratto con Waffle: - -```bash -npx waffle -``` - -Facile, vero? Nella cartella `build/` sono comparsi due file corrispondenti al contratto e all'interfaccia. Li useremo dopo per i test. - -### **3. Test** {#3-testing} - -Creiamo un file chiamato `AmIRichAlready.test.ts` per il test reale. Prima di tutto, dobbiamo gestire le importazioni. Ci serviranno dopo: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -A parte le dipendenze JS, dobbiamo importare il contratto e l'interfaccia creati: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle usa `chai` per il test. Tuttavia, prima di poterlo usare, dobbiamo inserire i matcher di Waffle in chai: - -```typescript -use(solidity) -``` - -Dobbiamo implementare la funzione `beforeEach()` che ripristinerà lo stato del contratto prima di ogni test. Prima pensiamo a cosa ci serve. Per distribuire un contratto servono due cose: un portafoglio e un contratto ERC20 distribuito da passare come argomento per il contratto `AmIRichAlready`. - -Prima creiamo un portafoglio: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Poi dobbiamo distribuire un contratto ERC20. Ecco la parte complicata: abbiamo solo un'interfaccia. Questa è la parte in cui Waffle ci viene in aiuto. Waffle ha la funzione magica `deployMockContract()` che crea un contratto usando solo l'_abi_ dell'interfaccia: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Ora con il portafoglio e l'ERC20 distribuito, possiamo continuare e distribuire il contratto `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -A questo punto, la funzione `beforeEach()` è finita. Il file `AmIRichAlready.test.ts` avrà il seguente aspetto: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Scriviamo il primo test per il contratto `AmIRichAlready`. Cosa pensi dovrebbe fare il test? Esatto! Dobbiamo controllare se siamo già ricchi :) - -Ma aspetta un attimo. Come farà il nostro contratto simulato a sapere che valori restituire? Non abbiamo implementato alcuna logica per la funzione `balanceOf()`. Di nuovo, Waffle ci viene in aiuto. Il nostro contratto simulato ha contenuto interessante: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Con queste informazioni possiamo finalmente scrivere il primo test: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Suddividiamo questo test in più parti: - -1. Impostiamo il contratto ERC20 simulato per restituire il saldo di 999999 token. -2. Controlliamo se il metodo `contract.check()` restituisce `false`. - -Siamo pronti a scatenare la bestia: - -![Un test superato](./test-one.png) - -Quindi il test funziona, ma... si può ancora migliorare. La funzione `balanceOf()` restituirà sempre 99999. Possiamo migliorarla specificando un portafoglio per cui la funzione deve restituire qualcosa, proprio come un vero contratto: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Finora, abbiamo testato solo il caso in cui non siamo abbastanza ricchi. Testiamo invece l'opposto: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Esegui i test... - -![Due test superati](test-two.png) - -...ed ecco qui! Il nostro contratto sembra funzionare come previsto :) - -## Test delle chiamate del contratto {#testing-contract-calls} - -Ricapitoliamo cosa abbiamo fatto finora. Abbiamo testato la funzionalità del contratto `AmIRichAlready` che sembra funzionare correttamente. Quindi abbiamo finito, giusto? Non proprio. Waffle ci consente di testare il nostro contratto ancora più a fondo. Ma come esattamente? Beh, nell'arsenale di Waffle ci sono i matcher `calledOnContract()` e `calledOnContractWith()`. Ci consentiranno di verificare se il contratto ha chiamato il contratto simulato ERC20. Ecco un test di base con uno di questi matcher: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Possiamo andare persino oltre e migliorare questo test con l'altro matcher che ho indicato: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Controlliamo se i test sono corretti: - -![Tre test superati](test-three.png) - -Ottimo, tutti i test danno luce verde. - -Testare le chiamate di contratto con Waffle è facilissimo. Ma ecco la parte migliore. Questi matcher funzionano sia con contratti normali che simulati! Questo perché Waffle registra e filtra le chiamate all'EVM piuttosto che inserire il codice, come invece fanno librerie di testing popolari di altre tecnologie. - -## Il traguardo {#the-finish-line} - -Congratulazioni! Ora sai come usare Waffle per testare le chiamate di contratto e i contratti simulati dinamicamente. Ci sono funzionalità ben più interessanti da scoprire. Ti consiglio di tuffarti nella documentazione di Waffle. - -La documentazione di Waffle è disponibile [qui](https://ethereum-waffle.readthedocs.io/). - -Il codice sorgente di questo tutorial si può trovare [qui](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Altri tutorial che potrebbero interessarti: - -- [Test di Smart Contract con Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 4de539e1148..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Tutorial Waffle Hello world con hardhat ed ethers" -description: Crea il tuo primo progetto Waffle con hardhat ed ethers.js -author: "MiZiet" -tags: - - "waffle" - - "smart contract" - - "Solidity" - - "test" - - "hardhat" - - "ethers.js" -skill: beginner -lang: it -published: 2020-10-16 ---- - -In questo tutorial di [Waffle](https://ethereum-waffle.readthedocs.io), impareremo come configurare un semplice progetto di smart contract "Hello World" usando [hardhat](https://hardhat.org/) e [ethers.js](https://docs.ethers.io/v5/). Quindi impareremo come aggiungere una nuova funzionalità allo smart contract e come testarla con Waffle. - -Iniziamo creando un nuovo progetto: - -```bash -yarn init -``` - -o - -```bash -npm init -``` - -e installando i pacchetti necessari: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -o - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Il prossimo passaggio consiste nel creare un progetto hardhat di esempio eseguendo `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Seleziona `Create a sample project` - -La struttura del nostro progetto sarà simile a: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Ora parliamo di alcuni di questi file: {#now-lets-talk} - -- Greeter.sol - il nostro Smart Contract scritto in Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Il nostro smart contract è divisibile in tre parti: - -1. costruttore - posizione in cui dichiariamo una variabile di tipo di stringa chiamata `greeting`, -2. funzione greet - funzione che restituirà `greeting` quando chiamata, -3. funzione setGreeting - funzione che ci consente di cambiare il valore di `greeting`. - -- sample-test.js - file per il test - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Il prossimo passaggio consiste nel compilare il contratto ed eseguire test: {#compiling-and-testing} - -I test di Waffle usano Mocha (un framework di test) con Chai (una libreria di asserzione). È sufficiente eseguire `npx hardhat test` e attendere che compaia il messaggio seguente. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Finora tutto bene, adesso aggiungiamo un po' di complessità al nostro progetto {#adding-complexity} - -Immagina una situazione in cui qualcuno aggiunge una stringa vuota come formula di saluto. Non sarebbe un bel saluto, vero? -Assicuriamoci che non succeda: - -Vogliamo usare `revert` di Solidity quando qualcuno passa una stringa vuota. Un aspetto positivo è che possiamo facilmente testare questa funzionalità con il matcher chai di Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Sembra che il nostro nuovo test non sia riuscito: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Implementiamo questa funzionalità nel nostro smart contract: - -```solidity -require(bytes(_greeting).length > 0, "Il saluto non dovrebbe esser vuoto"); -``` - -Ora, la nostra funzione setGreeting somiglia a: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Eseguiamo di nuovo i test: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Congratulazioni! Ce l'hai fatta :) - -### Conclusioni {#conclusion} - -Abbiamo realizzato un semplice progetto con Waffle, Hardhat ed ethers.js. Abbiamo imparato come configurare un progetto, aggiungere un test e implementare nuove funzionalità. - -Per informazioni su altri utili matcher chai per testare gli smart contract, consulta la [documentazione ufficiale di Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index d440693878a..00000000000 --- a/public/content/translations/it/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Testare semplici contratti intelligenti con la libreria Waffle -description: Tutorial per principianti -author: Ewa Kowalska -tags: - - "contratti intelligenti" - - "solidity" - - "Waffle" - - "test" -skill: beginner -lang: it -published: 2021-02-26 ---- - -## In questo tutorial imparerai come {#in-this-tutorial-youll-learn-how-to} - -- Testare le modifiche del saldo del portafoglio -- Testare l'emissione di eventi con gli argomenti specificati -- Imporre il ripristino di una transazione - -## Premesse {#assumptions} - -- Sei in grado di creare un nuovo progetto JavaScript o TypeScript -- Hai delle esperienze di base con i test in JavaScript -- Hai utilizzato dei gestori di pacchetti come yarn o npm -- Possiedi conoscenze molto essenziali dei contratti intelligenti e di Solidity - -## Primi passi {#getting-started} - -Il tutorial dimostra la configurazione di prova e opera utilizzando yarn, ma non ci sono problemi se preferisci npm: fornirò gli adeguati riferimenti alla [documentazione](https://ethereum-waffle.readthedocs.io/en/latest/index.html) ufficiale di Waffle. - -### Installa dipendenze {#install-dependencies} - -[Aggiungi](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) ethereum-waffle e le dipendenze di TypeScript alle dipendenze di sviluppo del tuo progetto. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -### Esempio di contratto intelligente {#example-smart-contract} - -Durante il tutorial lavoreremo a un esempio di contratto intelligente semplice: EtherSplitter. Non fa molto, tranne che consentire a chiunque di inviare wei e dividerli uniformemente tra due destinatari predefiniti. La funzione di divisione richiede che il numero di wei sia pari, altrimenti si ripristinerà. Per entrambi i destinatari esegue un trasferimento di wei, seguito dall'emissione dell'evento Trasferimento. - -Posiziona il frammento del codice di EtherSplitter in `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -### Compila il contratto {#compile-the-contract} - -Per [compilare](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) il contratto, aggiungi il seguente elemento al file package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Poi, crea un file di configurazione di Waffle nella cartella di root del progetto, `waffle.json`, e incolla qui la seguente configurazione: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Esegui `yarn build`. Di conseguenza, la cartella `build` apparirà con il contratto compilato di EtherSplitter nel formato JSON. - -### Testare la configurazione {#test-setup} - -Testare con Waffle richiede l'utilizzo di abbinatori Chai e Mocha, quindi, devi [aggiungerli](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) al tuo progetto. Aggiorna il tuo file package.json e aggiungi l'elemento `test` nella parte degli script: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Se desideri [eseguire](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) i tuoi test, basta eseguire `yarn test`. - -## Test {#testing} - -Ora, crea la cartella `test` e crea il nuovo file `test\EtherSplitter.test.ts`. Copia il seguente frammento e incollalo sul nostro file di test. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -Solo due parole prima di iniziare. `MockProvider` offre una versione fittizia della blockchain. Inoltre, fornisce portafogli fittizi che ci serviranno per testare il contratto di EtherSplitter. Possiamo ottenere fino a dieci portafogli chiamando il metodo `getWallets()` sul fornitore. Nell'esempio, otteniamo tre portafogli: per il mittente e per i due destinatari. - -Quindi, dichiariamo una variabile detta "splitter" (divisore), che è il nostro contratto fittizio EtherSplitter. È creato prima di ogni esecuzione di un singolo test dal metodo `deployContract`. Questo metodo simula la distribuzione di un contratto dal portafoglio passato come primo parametro (nel nostro caso, il portafoglio del mittente). Il secondo parametro è l'ABI e il bytecode del contratto testato; qui, passiamo il file json del contratto compilato EtherSplitter dalla cartella `build`. Il terzo parametro è un insieme con gli argomenti del costruttore del contratto che, nel nostro caso, sono gli indirizzi dei due destinatari. - -### changeBalances {#changebalances} - -Prima controlleremo se il metodo di divisione modifica effettivamente i saldi dei portafogli dei destinatari. Se dividiamo 50 wei dall'account del mittente, i saldi di entrambi i destinatari dovrebbero aumentare di 25 wei. Utilizzeremo l'abbinatore di Waffle "`changeBalances`: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Come primo parametro dell'abbinatore, passiamo un insieme di portafogli dei destinatari e, come secondo, un insieme degli aumenti previsti sugli account corrispondenti. Se desiderassimo verificare il saldo di un portafoglio specifico, potremmo anche utilizzare l'abbinatore `changeBalance`, che non richiede di passare insiemi, come nel seguente esempio: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Nota che in entrambi i casi di `changeBalance` e `changeBalances`, passiamo la funzione di divisione come richiamata, poiché l'abbinatore deve accedere allo stato dei saldi prima e dopo la chiamata. - -Poi, testeremo se l'evento Trasferimento è stato emesso dopo ogni trasferimento di wei. Ci rivolgeremo a un altro abbinatore da Waffle: - -### Emetti {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -L'abbinatore `emit` ci consente di verificare se un contratto ha emesso un evento alla chiamata di un metodo. Come parametri all'abbinatore `emit`, forniamo il contratto fittizio che prevediamo emetterà l'evento, insieme al nome di tale evento. Nel nostro caso, il contratto fittizio è `splitter` e il nome dell'evento è `Trasferimento`. Inoltre, possiamo verificare i valori precisi degli argomenti con cui è stato emesso l'evento; passiamo altrettanti argomenti all'abbinatore `withArgs`, come previsto dalla dichiarazione del nostro evento. Nel caso del contratto EtherSplitter, passiamo gli indirizzi del mittente e del destinatario insieme all'importo trasferito di wei. - -### revertedWith {#revertedwith} - -Come ultimo esempio verificheremo se la transazione è stata ripristinata, nel caso di un numero dispari di wei. Utilizzeremo l'abbinatore `revertedWith`: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -Il test, se superato, ci assicurerà che la transazione è stata effettivamente ripristinata. Tuttavia, deve anche verificarsi una corrispondenza esatta tra i messaggi passati nella dichiarazione `require` e il messaggio previsto in `revertedWith`. Se torniamo al codice del contratto EtherSplitter, nella dichiarazione `require` per l'importo di wei, forniamo il messaggio: "Importo di wei dispari non consentito". Questo corrisponde al messaggio che ci aspettiamo nel nostro test. Se non fossero stati uguali, il test sarebbe fallito. - -## Congratulazioni! {#congratulations} - -Hai compiuto il tuo primo grande passo verso il test dei contratti intelligenti con Waffle! diff --git a/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index be94fd1c2f8..00000000000 --- a/public/content/translations/ja/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: "Waffleを使って、ERC-20トークンをテストする" -description: "Waffleを使用して、Solidityで書かれたスマートコントラクトをテストしたり、スマートコントラクトのマッチャーを使用する方法について学ぶ。" -author: Vladislav Starostenko -tags: - - "Waffle" - - "スマートコントラクト" - - "Solidity" - - "テスト" - - "ERC-20" -skill: intermediate -lang: ja -published: 2020-10-16 ---- - -このチュートリアルでは、以下について学びます: - -- Waffleを使って、スマートコントラクトをテストする方法 -- Waffle上で、一般的なマッチャーを使ってスマートコントラクトをテストする方法 - -前提知識: - -- ターミナルを操作できる。 -- 新規の`JavaScript`プロジェクトを作成できる。 -- 数行の`Solidity`コードを書いたことがある。 -- いくつかのテストを`JavaScript`で作成したことがある。 -- `yarn`あるいは、JavaScriptsのパッケージインストーラである`npm`を使用したことがある。 - -上記に該当しない場合や、以下のコードを実際に作成するつもりがない方でも、容易に理解できる内容です。 - -## Waffleの簡単な紹介 {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io)は、スマートコントラクトの作成とテストのための最も先進的なライブラリです。 - -[JavaScript API](/developers/docs/apis/javascript/)であるethers-jsと連携して動作します。 - -詳細については、[Waffleのドキュメンテーション](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)をご覧ください! - -## クイックチュートリアル {#the-quick-tutorial} - -最初に、新規の`JavaScript`または`TypeScript`プロジェクトを作成します(ここでは`TS`を使用しますが、`JS`を使用しても問題ありません)。 - -以下のような構成になります: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## ステップ1:あなたのプロジェクトに、Waffleをインストールする([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation))。 {#step-1-install-waffle-in-your-project} - -まずはじめに、`ethereum-waffle`をインストールします。 このチュートリアルでは、次のように `yarn`を使用しますので、以下を実行すると`ethereum-waffle`がインストールされます: - -```bash - yarn add --dev ethereum-waffle -``` - -## ステップ2:スマートコントラクトを作成する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract)) {#step-2-write-a-smart-contract} - -このチュートリアルでは、[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol)の[ERC-20](https://openzeppelin.com)トークンを使用します。 - -`yarn`で以下を実行すると、`OpenZeppelin`がインストールされます。 - -```bash - yarn add @openzeppelin/contracts -D -``` - -次に、 `src`ディレクトリに`BasicToken.sol`コントラクトを作成します。 - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## ステップ3:スマートコントラクトをコンパイルします([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)) {#step-3-compile-your-smart-contract} - -スマートコントラクトをコンパイルするには、プロジェクトの`package.json`に以下のエントリを追加します: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -また、プロジェクトのメイン ディレクトリに`waffle.json`ファイルを追加します。 - -以下は、`waffle.json`の設定例です: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Waffleの設定については、[こちら](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration)をご覧ください。 - -次に、`yarn build`を実行してスマートコントラクトをコンパイルします。 - -Waffleがコントラクトをコンパイルし、JSONの出力結果を`build`ディレクトリ内に配置したことがわかります。 - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## ステップ4:スマートコントラクトをテストする([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-test-your-smart-contract} - -### ステップ 4.1:必要な依存関係をインストールします([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-1} - -スマートコントラクトを作成したら、さっそくテストしましょう。 テストには、`Waffle`を使用します。 - -`Waffle`のテストは、`Mocha`と`Chai`を使用して作成します。 他のテスト環境も使用できますが、`Waffle`マッチャーは `Chai`でのみ動作します。 - -そのため、`Chai`に依存関係を追加する必要があります: - -```bash - yarn add --dev mocha chai -``` - -### ステップ4.2:テストファイルを作成する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)) {#step-4-2} - -テストを作成するには、テストディレクトリに`BasicToken.test.ts`ファイルを作成する必要があります。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -トークンのデプロイには、`Waffle`の`deployContract`メソッドを使用します。 引数としては、作成したコントラクトとデフォルト残高をコンパイルしたjsonファイルである`wallet`を引き渡す必要があります。 - -`Waffle`では`wallet`を作成することもできるため、コントラクトをとても簡単にデプロイできます。 - -`wallet`の詳細については、 [こちら](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets)をご覧ください。デプロイ機能に関しては、[こちら](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts)をご覧ください。 - -それでは、ウォレット残高を確認する簡単なテストを作成してみましょう。 コントラクトのデプロイ時に1000の値を送信したため、ウォレット残高が1000トークンになっているはずですが、最初のテストではこれを確認します。 - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -テストを実行するには、 `yarn test`を使用します。 - -### ステップ4.3:イベントを出力する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events)) {#step-4-3} - -このチュートリアルでは、`Waffle`の中で最も便利なマッチャーを紹介したいと思いますので、一番便利なものから始めましょう。 - -`Waffle`は、どのイベントが発行されたのかをテストできます。 - -このチュートリアルでは、コントラクトの`送信`メソッドをテストします。 - -このテストでは、あるウォレットから別のウォレットへの送金を行い、 `送信`イベントの呼び出しが発生したかを確認します。 - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -このマッチャーの大きな利点のひとつは、`withArgs`をテストに追加することで、どの引数がこのイベントを呼び出したのかを確認できる点です。 - -これにより、関数が正しく呼び出されたことを確認できます! - -### ステップ4.4:メッセージと共に元に戻す([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message)) {#step-4-4} - -`Waffle`では、トランザクションを元に戻す際に添付されたメッセージもテストできます。 - -ここでは、`revertedWith`マッチャーを使って確認します。 - -ウォレット残高を上回る額の送金を実行するテストを作成することができます。 その上で、同一のメッセージと共にトランザクションが元に戻されたかどうかを確認できます。 - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### ステップ4.5:トークン残高を変更する([ドキュメントのリンク](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance)) {#step-4-5} - -`Waffle`では、ウォレット残高の変化も確認できます! - -`changeTokenBalance`マッチャーを使用して残高の変化を確認することができ、複数のアカウントを対象とする場合は`changeTokenBalances`で確認できます。 - -このマッチャーでは、`numbers`、`strings`、`BigNumbers`を残高の変更として受け取ることができますが、アドレスはウォレットまたはコントラクトとして指定する必要があります。 - -次のテストを作成してみましょう: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -これは、1つのウォレットを対象とするテストです。 - -以下は、複数のウォレットを対象とする場合です: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -このトランザクションは、コールバックとして(呼び出しの前に残高を確認する必要があります)、あるいは他のトンラザクションへの応答として受け渡すことが想定されています。 - -## お疲れ様でした! {#congratulations} - -**おめでとうございます! チュートリアルは、これで終了です。 Waffleでスマートコントラクトをテストするための最初の大きな一歩を踏み出すことができました。** - -**このチュートリアルのコードについては、[こちら](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website)でアクセスできます。** - -**`Waffle`についての詳細なドキュメンテーションは、[こちら](https://getwaffle.io)からアクセスできます。** diff --git a/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 899c71a6173..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle: 動的モッキングとコントラクト呼び出しのテスト" -description: "動的モッキングとコントラクト呼び出しのテストのためのWaffle上級チュートリアル" -author: "Daniel Izdebski" -tags: [ "Waffle", "スマートコントラクト", "Solidity", "テスト", "モックアップ作成" ] -skill: intermediate -lang: ja -published: 2020-11-14 ---- - -## このチュートリアルについて {#what-is-this-tutorial-about} - -このチュートリアルでは、以下の方法を学びます: - -- 動的モッキングの使用 -- スマートコントラクト間のインタラクションをテストする - -前提知識: - -- `Solidity`で簡単なスマートコントラクトを記述する方法をすでに知っている -- `JavaScript`と`TypeScript`に精通している -- 他の`Waffle`チュートリアルを完了したか、`Waffle`についてある程度の知識がある - -## 動的モッキング {#dynamic-mocking} - -動的モッキングはなぜ便利なのでしょうか? これにより、統合テストの代わりに単体テストを作成できます。 これは何を意味するのでしょうか。 つまり、スマートコントラクトの依存関係を気にする必要がなく、完全に分離してすべてのテストを行えるということです。 その具体的な方法をご紹介します。 - -### **1. プロジェクト** {#1-project} - -始める前に、簡単なnode.jsプロジェクトを準備する必要があります。 - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# またはnpmを使用している場合 -npm init -``` - -まず、TypeScriptとテストの依存関係であるmochaとchaiを追加しましょう。 - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# またはnpmを使用している場合 -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -では、`Waffle`と`ethers`を追加しましょう: - -```bash -yarn add --dev ethereum-waffle ethers -# またはnpmを使用している場合 -npm install ethereum-waffle ethers --save-dev -``` - -これで、プロジェクトの構成は以下のようになります: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. スマートコントラクト** {#2-smart-contract} - -動的モッキングを開始するには、依存関係のあるスマートコントラクトが必要です。 ご心配なく。こちらで用意してあります。 - -これは`Solidity`で書かれた簡単なスマートコントラクトで、唯一の目的は私たちがお金持ちかどうかをチェックすることです。 ERC20トークンを使って、十分なトークンを保有しているかチェックします。 これを`./contracts/AmIRichAlready.sol`に配置してください。 - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -動的モッキングを使いたいので、ERC20全体は必要ありません。そのため、関数が1つだけのIERC20インターフェースを使用しています。 - -では、このコントラクトをビルドしましょう。 そのために`Waffle`を使用します。 まず、コンパイルオプションを指定する簡単な`waffle.json`設定ファイルを作成します。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -これでWaffleでコントラクトをビルドする準備ができました: - -```bash -npx waffle -``` - -簡単でしょう? `build/`フォルダに、コントラクトとインターフェースに対応する2つのファイルが作成されました。 これらは後でテストに使用します。 - -### **3. テスト** {#3-testing} - -実際のテストのために、`AmIRichAlready.test.ts`というファイルを作成しましょう。 まず、インポートを記述します。 これらは後で必要になります: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -JSの依存関係とは別に、ビルドしたコントラクトとインターフェースをインポートする必要があります: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffleはテストに`chai`を使用します。 ただし、使用する前にWaffleのマッチャーをchai自体に注入する必要があります: - -```typescript -use(solidity) -``` - -各テストの前にコントラクトの状態をリセットする`beforeEach()`関数を実装する必要があります。 まず、そこで何が必要になるかを考えてみましょう。 コントラクトをデプロイするには、ウォレットと、`AmIRichAlready`コントラクトの引数として渡すためのデプロイ済みERC20コントラクトの2つが必要です。 - -まず、ウォレットを作成します: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -次に、ERC20コントラクトをデプロイする必要があります。 ここが難しいところです。インターフェースしかありません。 ここでWaffleが助けになります。 Waffleには、インターフェースのABIのみを使用してコントラクトを作成する、魔法のような`deployMockContract()`関数があります: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -ウォレットとデプロイ済みのERC20の両方を使用して、`AmIRichAlready`コントラクトをデプロイできます: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -以上で、`beforeEach()`関数は完成です。 ここまでの`AmIRichAlready.test.ts`ファイルは以下のようになります: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -`AmIRichAlready`コントラクトの最初のテストを書きましょう。 テストでは何をすべきだと思いますか? ええ、その通りです! 私たちがお金持ちかどうかをチェックすべきですね :) - -しかし、少し待ってください。 モックコントラクトは、どの値を返すかどうやって知るのでしょうか? `balanceOf()`関数のロジックを実装していません。 ここでもWaffleが役立ちます。 モックコントラクトには、このような新しい気の利いた機能が追加されました: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -この知識をもとに、ようやく最初のテストを書くことができます: - -```typescript -it("ウォレットの保有するトークンが1,000,000未満の場合にfalseを返す", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -このテストを分解してみましょう: - -1. モックERC20コントラクトが常に999,999トークンの残高を返すように設定します。 -2. `contract.check()`メソッドが`false`を返すかどうかを確認します。 - -準備ができたので、実行してみましょう。 - -![1つのテストが合格](./test-one.png) - -テストは動作しますが、しかし... まだ改善の余地があります。 `balanceOf()`関数は常に99999を返します。 実際のコントラクトのように、関数が値を返すウォレットを指定することで改善できます: - -```typescript -it("ウォレットの保有するトークンが1,000,001未満の場合にfalseを返す", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -ここまでは、十分にお金持ちでない場合のみをテストしました。 代わりに、その逆をテストしてみましょう: - -```typescript -it("ウォレットが少なくとも1,000,001トークンを保有している場合にtrueを返す", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -テストを実行すると... - -![2つのテストが合格](test-two.png) - -...これで完了です! コントラクトは意図通りに動作しているようです :) - -## コントラクト呼び出しのテスト {#testing-contract-calls} - -これまでの作業をまとめましょう。 `AmIRichAlready`コントラクトの機能をテストし、正しく動作しているようです。 これで完了ということですよね? 必ずしもそうではありません。 Waffleを使えば、コントラクトをさらにテストすることができます。 しかし、具体的にはどうやって? Waffleには、`calledOnContract()`と`calledOnContractWith()`というマッチャーが用意されています。 これらにより、コントラクトがERC20モックコントラクトを呼び出したかどうかをチェックできます。 これらのマッチャーの1つを使用した基本的なテストは次のとおりです: - -```typescript -it("コントラクトがERC20トークンでbalanceOfを呼び出したかチェックする", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -先ほどお話ししたもう一方のマッチャーで、このテストをさらに改善することができます: - -```typescript -it("コントラクトがERC20トークンで特定のウォレットに対してbalanceOfを呼び出したかチェックする", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -テストが正しいかチェックしましょう: - -![3つのテストが合格](test-three.png) - -素晴らしい、すべてのテストに合格しました。 - -Waffleを使ったコントラクト呼び出しのテストは非常に簡単です。 そして、ここからが一番すごいところです。 これらのマッチャーは、通常のコントラクトとモックコントラクトの両方で動作します! これは、他の技術で一般的なテストライブラリのようにコードを注入するのではなく、WaffleがEVM呼び出しを記録・フィルタリングするためです。 - -## ゴール {#the-finish-line} - -おめでとうございます! これで、Waffleを使ってコントラクト呼び出しをテストし、コントラクトを動的にモックする方法がわかりました。 他にも発見すべき興味深い機能がたくさんあります。 Waffleのドキュメンテーションを深く読んでみることをお勧めします。 - -Waffleのドキュメンテーションは[こちら](https://ethereum-waffle.readthedocs.io/)でご覧いただけます。 - -このチュートリアルのソースコードは[こちら](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls)にあります。 - -こちらもおすすめのチュートリアルです: - -- [Waffleでスマートコントラクトをテストする](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 05fdd1a50aa..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "WaffleでHardhatとethersを使って「Hello world!」と出力するチュートリアル" -description: "Hardhatとethers.jsを使って、はじめてのWaffleプロジェクトを作成する" -author: "MiZiet" -tags: - [ - "Waffle", - "スマートコントラクト", - "Solidity", - "テスト", - "Hardhat", - "ethers.js" - ] -skill: beginner -lang: ja -published: 2020-10-16 ---- - -この[Waffle](https://ethereum-waffle.readthedocs.io)チュートリアルでは、[hardhat](https://hardhat.org/)と[ethers.js](https://docs.ethers.io/v5/)を使い、シンプルな「Hello world」スマートコントラクトプロジェクトをセットアップする方法を学びます。 次に、スマートコントラクトに新しい機能を追加する方法と、Waffleでそれをテストする方法を学びます。 - -まず、新しいプロジェクトを作成することから始めましょう: - -```bash -yarn init -``` - -または - -```bash -npm init -``` - -そして、必要なパッケージをインストールします: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -または - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -次のステップでは、`npx hardhat`を実行して、Hardhatのサンプルプロジェクトを作成します。 - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Hardhat v2.0.3へようこそ 👷‍ - -? 何をしますか? … -❯ サンプルプロジェクトを作成する -空のhardhat.config.jsを作成する -終了 -``` - -「Create a sample project」を選択します - -プロジェクトの構成は次のようになります: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### では、これらのファイルについて見ていきましょう: {#now-lets-talk} - -- Greeter.sol - Solidityで書かれたスマートコントラクトです。 - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -このスマートコントラクトは、3つの部分に分けられます: - -1. constructor - `greeting`という名前のstring型変数を宣言します。 -2. function greet - 呼び出されたときに`greeting`を返す関数です。 -3. function setGreeting - `greeting`の値を変更できるようにする関数です。 - -- sample-test.js - テストファイルです - -```js -describe("Greeter", function () { - it("変更されると新しい挨拶を返すはず", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### 次のステップでは、コントラクトのコンパイルとテストの実行を行います: {#compiling-and-testing} - -Waffleのテストでは、Mocha (テストフレームワーク) とChai (アサーションライブラリ) を使用します。 `npx hardhat test`を実行し、次のメッセージが表示されるのを待つだけです。 - -```bash -✓ 変更されると新しい挨拶を返すはず -``` - -### ここまでは順調です。プロジェクトにもう少し複雑な機能を追加してみましょう {#adding-complexity} - -誰かが挨拶として空の文字列を追加する状況を想像してみてください。 それでは心のこもった挨拶にはなりませんよね? -そうならないようにしてみましょう: - -誰かが空の文字列を渡した場合に、Solidityの`revert`を使いたいと思います。 幸いなことに、WaffleのChaiマッチャー`to.be.revertedWith()`を使えば、この機能を簡単にテストできます。 - -```js -it("空の文字列を渡したときにリバートするはず", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -新しいテストはパスしなかったようです: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ 変更されると新しい挨拶を返すはず (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) 空の文字列を渡したときにリバートするはず - - - 1件成功 (2s) - 1件失敗 -``` - -この機能をスマートコントラクトに実装しましょう: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -これで、setGreeting関数は次のようになります: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -もう一度テストを実行してみましょう: - -```bash -✓ 変更されると新しい挨拶を返すはず (1467ms) -✓ 空の文字列を渡したときにリバートするはず (276ms) - -2件成功 (2s) -``` - -おめでとうございます! やり遂げましたね :) - -### 結論 {#conclusion} - -Waffle、Hardhat、ethers.jsを使ってシンプルなプロジェクトを作成しました。 プロジェクトのセットアップ、テストの追加、新機能の実装方法を学びました。 - -スマートコントラクトをテストするための、さらに優れたChaiマッチャーについては、[Waffleの公式ドキュメント](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)を確認してください。 diff --git a/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 01ca363fab1..00000000000 --- a/public/content/translations/ja/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "Waffleライブラリを使用したシンプルなスマートコントラクトのテスト" -description: "初心者用チュートリアル" -author: Ewa Kowalska -tags: [ "スマートコントラクト", "Solidity", "Waffle", "テスト" ] -skill: beginner -lang: ja -published: 2021-02-26 ---- - -## このチュートリアルでは、次の方法を学びます {#in-this-tutorial-youll-learn-how-to} - -- ウォレット残高の変更をテストする -- 指定された引数を持つイベントの発行をテストする -- トランザクションがrevertされたことをアサートする - -## 前提条件 {#assumptions} - -- 新規のJavaScriptまたはTypeScriptのプロジェクトを作成できる -- JavaScriptのテストの基本的な経験がある -- yarnやnpmなどのパッケージマネージャーを使用したことがある -- スマートコントラクトおよびSolidityのごく基本的な知識を持っている - -## はじめに {#getting-started} - -このチュートリアルでは、yarnを使ったテストのセットアップと実行を実演しますが、npmがお好みであれば問題ありません。公式Waffleの[ドキュメント](https://ethereum-waffle.readthedocs.io/en/latest/index.html)への適切なリファレンスを記載します。 - -## 依存関係をインストール {#install-dependencies} - -ethereum-waffleとtypescriptの依存関係をプロジェクトの開発依存関係に[追加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)します。 - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## スマートコントラクトの例 {#example-smart-contract} - -このチュートリアルでは、EtherSplitterというシンプルなスマートコントラクトの例に取り組みます。 誰かがweiを送金し、それを2つの事前定義された受信者の間で均等に分割できるようにする以外に、特別な機能はありません。 -split関数ではweiの数が偶数でなければなりません。さもないと処理は取り消されます。 両方の受信者に対して、weiの送金を実行し、続いてTransferイベントを発行します。 - -`src/EtherSplitter.sol`に、EtherSplitterコードのスニペットを配置します。 - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## コントラクトをコンパイルする {#compile-the-contract} - -コントラクトを[コンパイル](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)するには、package.jsonファイルに次のエントリを追加します。 - -```json -"scripts": { - "build": "waffle" - } -``` - -次に、プロジェクトのルートディレクトリにWaffleの設定ファイル (`waffle.json`) を作成し、次の設定をそこに貼り付けます。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -`yarn build` を実行します。 結果として、`build`ディレクトリに、コンパイルされたEtherSplitterコントラクトがJSON形式で現れます。 - -## テストのセットアップ {#test-setup} - -Waffleを使ったテストにはChaiマッチャーとMochaが必要なので、それらをプロジェクトに[追加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)する必要があります。 package.jsonファイルを更新し、scriptsの部分に`test`エントリを追加してください。 - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -テストを[実行](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests)したい場合は、`yarn test`を実行するだけです。 - -## テスト {#testing} - -それでは、`test`ディレクトリを作成し、新しいファイル `test\EtherSplitter.test.ts`を作成してください。 -以下のスニペットをコピーして、テストファイルに貼り付けてください。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("イーサスプリッター", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // ここにテストを追加 -}) -``` - -始める前に、少し解説をします。 -`MockProvider`は、ブロックチェーンのモックバージョンを作成します。 また、EtherSplitterコントラクトのテストで役立つモックウォレットも提供します。 このプロバイダーで、`getWallets()`メソッドを呼び出すと最大10個までウォレットを取得することができます。 この例では、送信者用と2人の受信者用の3つのウォレットを取得します。 - -次に、「splitter」という変数を宣言します。これは、EtherSplitterコントラクトのモックです。 このモックは、単一のテストを実行する前に`deployContract`メソッドによって作成されます。 当該のメソッドは、最初のパラメータとして渡されたウォレット (この場合は送信者のウォレット) からコントラクトのデプロイメントをシミュレートします。 2番目のパラメータは、テストされるコントラクトのABIとバイトコードです。コンパイルされたEtherSplitterコントラクトのjsonファイルを`build`ディレクトリから渡します。 3番目のパラメータは、コントラクトのコンストラクタ引数を持つ配列です。この場合、2人の受信者のアドレスです。 - -## changeBalances {#changebalances} - -まず、splitメソッドによって実際に受取人のウォレットの残高が変わるかどうかを確認します。 送信者のアカウントから50 weiを分割すると、両方の受信者の残高が25 wei増えることが期待されます。 ここで、Waffleの`changeBalances`マッチャーを使います。 - -```ts -it("アカウントの残高を変更する", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -マッチャーの最初のパラメータとして、受信者のウォレットの配列を渡し、2番目のパラメータとして、対応するアカウントで予想される増加分を配列で渡します。 -特定のウォレットの残高を確認したい場合は、以下の例のように、配列を渡さなくても`changeBalance`マッチャーを使えます。 - -```ts -it("アカウントの残高を変更する", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -`changeBalance`と`changeBalances`のどちらの場合も、マッチャーが呼び出しの前後に残高の状態にアクセスする必要があるため、split関数をコールバックとして渡すことに注意してください。 - -次に、weiの各転送後にTransferイベントが発行されたかどうかをテストします。 それでは、Waffleの別のマッチャーに移ります。 - -## Emit {#emit} - -```ts -it("最初の受信者への転送時にイベントを発行する", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("2番目の受信者への転送時にイベントを発行する", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit`マッチャーを使うと、メソッドの呼び出し時にコントラクトがイベントを発行したかどうかを確認できます。 `emit`マッチャーへのパラメータとして、イベントを発行することが予期されるモックコントラクトとそのイベントの名前を渡します。 この場合、モックコントラクトは`splitter`で、イベント名は`Transfer`です。 また、イベントの発行で引数の正確な値を検証することもできます。その場合、イベントの宣言で期待される数の引数を`withArgs`マッチャーに渡します。 EtherSplitterコントラクトの場合では、送金されるwei単位の金額とともに送信者と受信者のアドレスを渡します。 - -## revertedWith {#revertedwith} - -最後の例として、weiの数が奇数の場合にトランザクションが取り消されるかどうかを確認します。 ここでは、`revertedWith`マッチャーを使います。 - -```ts -it("weiの量が奇数の場合にrevertする", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -このテストをパスすれば、トランザクションが実際に取り消されたことが保証されます。 ただし、`require`ステートメントで渡したメッセージと、`revertedWith`で期待しているメッセージとが完全に一致している必要があります。 EtherSplitterコントラクトのコードに戻ると、weiの量に対する`require`ステートメントで、「Uneven wei amount not allowed」というメッセージが表示されます。 これは、テストで予期されるメッセージと一致します。 それらが等しくなければ、テストは失敗します。 - -## おめでとうございます! {#congratulations} - -Waffleでスマートコントラクトをテストするための最初の大きな一歩を踏み出すことができました。 diff --git a/public/content/translations/pl/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/pl/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index f9dbf6311b5..00000000000 --- a/public/content/translations/pl/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,297 +0,0 @@ ---- -title: "Waffle: Dynamiczne tworzenie atrap i testowanie wywołań kontraktów" -description: Zaawansowany samouczek Waffle do używania dynamicznego tworzenia atrap i testowania wywołań kontraktów -author: "Daniel Izdebski" -tags: - - "waffle" - - "inteligentne kontrakty" - - "solidity" - - "testowanie" - - "tworzenie atrap" -skill: intermediate -lang: pl -published: 2020-11-14 ---- - -## O czym jest ten samouczek? {#what-is-this-tutorial-about} - -Z tego samouczka dowiesz się, jak: - -- uużywać dynamicznego tworzenia atrap -- testować interakcje między inteligentnymi kontraktami - -Założenia: - -- wiesz już, jak napisać prosty inteligentny kontrakt w `Solidity ` -- znasz się na `JavaScript` i `TypeScript` -- zapoznałeś się z innymi samouczkami `Waffle` lub wiesz coś na ten temat - -## Dynamiczne tworzenie atrap {#dynamic-mocking} - -Dlaczego dynamiczne tworzenie atrap jest przydatne? No cóż, pozwala nam pisać testy jednostkowe zamiast testów integracyjnych. Co to oznacza? Oznacza to, że nie musimy martwić się zależnościami inteligentnych kontraktów, dlatego możemy je przetestować w całkowicie izolacji. Pozwolę sobie pokazać, jak dokładnie możesz to zrobić. - -### **1. Projekt** {#1-project} - -Zanim zaczniemy musimy przygotować prosty projekt node.js: - -```bash -$ mkdir dynamic-mocking -$ cd dynamic-mocking -$ mkdir contracts src - -$ yarn init -# or if you're using npm -$ npm init -``` - -Zacznijmy od dodania zależności typescript i test — mokka i chai: - -```bash -$ yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# lub jeśli używasz npm $ npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Teraz dodajmy `Waffle` i `ethers`: - -```bash -$ yarn add --dev ethereum-waffle ethers -# or if you're using npm -$ npm install ethereum-waffle ethers --save-dev -``` - -Twoja struktura projektu powinna teraz wyglądać tak: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Inteligentny kontrakt** {#2-smart-contract} - -Aby rozpocząć dynamiczne tworzenie atrapy, potrzebujemy inteligentnego kontraktu z zależnościami. Nie martw się, pomyślałem o tym! - -Oto prosty inteligentny kontrakt napisany w `Solidity`, którego jedynym celem jest sprawdzenie, czy jesteśmy bogaci. Używa tokena ERC20 do sprawdzenia, czy mamy wystarczającą ilość tokenów. Umieść go w `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Ponieważ chcemy używać dynamicznego tworzenia atrap, nie potrzebujemy całego ERC20, dlatego używamy interfejsu IERC20 z tylko jedną funkcją. - -Nadszedł czas, aby zbudować ten kontrakt! W tym celu użyjemy `Waffle`. Najpierw stworzymy prosty plik konfiguracyjny `waffle.json`, który określa opcje kompilacji. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Teraz jesteśmy gotowi zbudować kontrakt z Waffle: - -```bash -$ npx waffle -``` - -Łatwe, prawda? W folderze `build/` pojawiły się dwa pliki odpowiadające umowie i interfejsowi. Wykorzystamy je później do testowania. - -### **3. Testowanie** {#3-testing} - -Utwórzmy plik o nazwie `AmIRichAlready.test.ts` dla bieżącego testu. Przede wszystkim musimy poradzić sobie z importem. Będziemy ich potrzebować na później: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Z wyjątkiem zależności JS, musimy zaimportować naszą wbudowaną umowę i interfejs: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle używa `chai` do testowania. Zanim jednak będziemy mogli go użyć, musimy wstrzyknąć wyrażenie matcher Waffle do samego chai: - -```typescript -use(solidity) -``` - -Musimy zaimplementować funkcję `beforeEach()`, która zresetuje stan kontraktu przed każdym testem. Zastanówmy się najpierw nad tym, czego tam potrzebujemy. Aby wdrożyć umowę, potrzebujemy dwóch rzeczy: portfela i wdrożonego kontraktu ERC20, aby przekazać go jako argument dla kontraktu `AmIRichAlready`. - -Po pierwsze, tworzymy portfel: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Następnie musimy wdrożyć umowę ERC20. Oto trudna część - mamy tylko interfejs. Jest to ta część, w której Waffle nas ratuje. Waffle posiada magiczną funkcję `wdrożenieMockContract()`, która tworzy kontrakt wykorzystujący tylko _abi_ interfejsu: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Teraz, zarówno z portfelem, jak i z ERC20, możemy kontynuować i wdrożyć kontrakt `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Po tym wszystkim nasza funkcja `beforeEach()` została zakończona. Jak dotąd plik `AmIRichAlready.test.ts` powinien wyglądać tak: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Zapiszmy pierwszy test do kontraktu `AmIRichAlready`. Czy uważasz, że powinniśmy mieć na uwadze nasz test? Tak, masz rację! Powinniśmy sprawdzić, czy już jesteśmy bogaci :) - -Ale poczekaj sekundę. Jak nasz pozorowany kontrakt będzie wiedział, jakie wartości należy zwrócić? Nie zaimplementowaliśmy żadnej logiki dla funkcji `balanceOf()`. Jeszcze raz Waffle może tu pomóc. Nasz pozorowany kontrakt ma teraz kilka nowych, fantazyjnych rzeczy: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Dzięki tej wiedzy możemy wreszcie napisać nasz pierwszy test: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Podzielmy ten test na części: - -1. Ustawiliśmy naszą próbną umowę ERC20 tak, aby zawsze zwracała saldo 999999 tokenów. -2. Sprawdź, czy metoda `contract.check()` zwraca `false`. - -Jesteśmy gotowi wystrzelić z grubej rury: - -![Jeden test zaliczony](./test-one.png) - -Tak więc test działa, ale... wciąż jest trochę miejsca na ulepszenia. Funkcja `balanceOf()` zawsze zwróci 99999. Możemy ją ulepszyć poprzez określenie portfela, dla którego funkcja powinna zwracać coś — tak jak prawdziwy kontrakt: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Jak dotąd przetestowaliśmy tylko przypadek, w którym nie jesteśmy wystarczająco bogaci. Przetestujmy przeciwnie: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Uruchomiłeś testy... - -![Zaliczenie dwóch testów](./test-two.png) - -...i tu jesteś! Nasza umowa wydaje się działać zgodnie z zamierzeniem :) - -## Testowanie wywołań kontraktów {#testing-contract-calls} - -Podsumujmy dotychczasowe osiągnięcia. Przetestowaliśmy funkcjonalność naszego kontraktu `AmIRichAlready` i wygląda na to, że działa poprawnie. To znaczy, że skończyliśmy, prawda? Nie całkiem! Waffle pozwala nam jeszcze bardziej przetestować nasz kontrakt. Ale jak dokładnie? No cóż, w arsenale Waffle'a znajduje się `calledOnContract()` i wyrażenia matcher `calledOnContractWith()`. Umożliwią nam one sprawdzenie, czy nasz kontrakt wywołał pozorowany kontrakt ERC20. Oto podstawowy test z jednym z tych wyrażeń: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Możemy pójść jeszcze dalej i ulepszyć ten test za pomocą innego wyrażenia matcher, o którym wam mówiłem: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Sprawdźmy, czy testy są poprawne: - -![Zaliczenie trzech testów](./test-three.png) - -Świetnie, wszystkie testy są zielone. - -Testowanie połączeń kontraktowych z Waffle jest bardzo łatwe. I oto najlepsza część. Te wyrażenia matcher działają zarówno z normalnymi, jak i próbnymi kontraktami! Wynika to z tego, że Waffle rejestruje i filtruje połączenia EVM zamiast wstrzykiwać kod, tak jak w przypadku popularnych bibliotek testowych dla innych technologii. - -## Meta {#the-finish-line} - -Gratulacje! Teraz wiesz jak korzystać z Waffle do dynamicznego testowania połączeń i modelowania kontraktów. Istnieją o wiele bardziej interesujące funkcje, które należy odkryć. Zalecam nurkowanie w dokumentacji Waffle. - -Dokumentacja Waffle'a jest dostępna [tutaj](https://ethereum-waffle.readthedocs.io/). - -Kod źródłowy dla tego samouczka można znaleźć [tutaj](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Samouczki mogą być interesujące: - -- [Testowanie inteligentnych kontraktów z Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/pt-br/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/pt-br/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index 4d2cec65779..00000000000 --- a/public/content/translations/pt-br/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: Testando tokens ERC-20 com Waffle -description: Aprenda como testar contratos inteligentes do Solidity e usar "matchers" de contratos inteligentes com o Waffle. -author: Vladislav Starostenko -tags: - - "waffle" - - "contratos inteligentes" - - "solidity" - - "testando" - - "erc-20" -skill: intermediate -lang: pt-br -published: 2020-10-16 ---- - -Neste tutorial, você aprenderá: - -- Crie testes para contratos inteligentes com Waffle -- Use alguns matchers populares para testar contratos inteligentes com Waffle - -Pressupostos: - -- você pode conseguir em um terminal, -- você pode criar um novo projeto de `JavaScript`, -- você escreveu algumas linhas de código `Solidity`, -- você escreveu alguns testes em `JavaScript`, -- você usou `yarn` or `npm`, o instalador de pacotes de JavaScript. - -Novamente. Caso algum desse tópicos não se apliquem, ou você não planeja reproduzir o código desse artigo, você provavelmente vai conseguir acompanhar o que vem a seguir. - -## Algumas palavras sobre Waffle {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) é a biblioteca mais avançada para escrever e testar contratos inteligentes. - -Funciona com a [API JavaScript](/developers/docs/apis/javascript/) ethers-js. - -Você pode ler mais detalhes na [documentação Waffle](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)! - -## O tutorial rápido {#the-quick-tutorial} - -Primeiro as coisas primeiras, crie um novo projeto de `JavaScript` ou `TypeScript` (Vou usar `TS`, mas se você usa `JS` não é um problema) : - -Alguma coisa como esta : - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## Passo #1: Instale o waffle no seu projeto [Link para o documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -To get started, install `ethereum-waffle`. Neste tutorial, eu usarei `yarn`, então para instalar `ethereum-waffle` executar: - -```bash - yarn add --dev ethereum-waffle -``` - -## Passo #2: Escreva um contrato inteligente [Link para documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -Neste tutorial, usarei o [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) token de [OpenZeppelin](https://openzeppelin.com). - -Então, adicione `OpenZeppelin` instalando-o com `yarn`: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Em seguida, crie o contrato `BasicToken.sol` no diretório `src`: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## Passo #3: Escreva um contrato inteligente [Link para documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Para compilar seu contrato inteligente, adicione a seguinte entrada no `package.json` do seu projeto: - -```json -{ - "scripts": { - "test": "jest" - } -} -``` - -Além disso, adicione o arquivo `waffle.json` na pasta principal do seu projeto. - -Um exemplo da configuração do `waffle.json`: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Leia mais sobre a configuração do Waffle [aqui](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration). - -Em seguida, execute `yarn build` para compilar seu contrato inteligente. - -Você deve ver que Waffle compilou seu contrato e colocou a saída JSON resultante dentro da pasta `compilação`. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## Passo #4: Escreva um contrato inteligente [Link para documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### Passo #4.1: Instale o waffle no seu projeto [Link para o documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Depois de criarmos com sucesso um Contrato Inteligente, podemos testá-lo. Vamos usar o `Waffle` para fazer isso. - -Os testes em `Waffle` são escritos usando `Mocha` juntamente com `Chai`. Podemos usar um ambiente de teste diferente mas `Waffle` matchers só trabalham com `Chai`. - -Então, precisamos adicionar `Chai` a nossas dependências : - -```bash - yarn add --dev mocha chai -``` - -### Passo #4.2: Escreva um contrato inteligente [Link para documento](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Para escrever nosso teste precisamos criar o arquivo `BasicToken.test.ts` em nosso diretório de teste. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Então, usamos o `deployContract` método de `Waffle`para publicar nosso token. Como argumentos, devemos passar a carteira ``, o arquivo json compilado de nosso contrato e saldo padrão. - -`Waffle` também nos permite criar uma `carteira`, o que facilita a implantação de um contrato. - -Você pode ler mais sobre a `carteira` [aqui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets) e pode ler mais sobre a função de implantação [aqui](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Vamos escrever um teste simples para verificar o saldo da nossa carteira. Desde que enviamos o valor 1000 durante a implantação do nosso contrato, o saldo de nossa carteira deve ser 1000 tokens, que podemos fazer check-in no primeiro teste. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Para executar o teste, use `yarn test` - -### Passo #4.3 Emitindo eventos [Link para o documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -Neste tutorial, eu quero mostrar a você as correspondências mais úteis do `Waffle`, então vamos começar com o primeiro. - -`Waffle` nos permite testar quais eventos foram emitidos. - -Neste tutorial, vou testar o método de `transfer` do nosso contrato. - -Neste teste, farei uma transferência de uma carteira para outra e verificarei se o evento `transfer` foi chamado. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Além disso, uma grande vantagem desse "matcher" é que podemos verificar com quais argumentos este evento foi chamado adicionando `withArgs` ao teste. - -Isso permitir-nos-á ter a certeza de que a nossa função está a ser chamada corretamente! - -### Passo #4.4 Emitindo eventos [Link para o documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` nos permite testar quais eventos foram emitidos. - -Usaremos `revertedWith` "matcher" em nosso teste para verificar. - -Podemos escrever um teste no qual realizaremos uma transferência por um valor maior do que o que fizemos na nossa carteira. E então verificaremos se a transação reverteu com a mensagem exata! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### Passo #4.5 Emitindo eventos [Link para o documento](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` nos permite verificar se há mudanças nos saldos das carteiras! - -Podemos usar o matcher `changeTokenBalance` para verificar a mudança do saldo ou o `changeTokenBalances` para uma conta múltipla. - -O matcher pode aceitar `números`, `strings` e `BigNumbers` como uma alteração de saldo, enquanto o endereço deve ser especificado como uma carteira ou um contrato. - -Vamos escrever o próximo teste: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -O teste acima é um teste para uma única carteira. - -E a próxima para múltiplas carteiras: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -A transação é esperada para ser passada como um callback (precisamos verificar o saldo antes da chamada) ou como uma resposta de transação. - -## Parabéns {#congratulations} - -**Parabéns! Você o fez através do meu tutorial. Você deu o seu primeiro grande passo para testar contratos inteligentes com Waffle.** - -**O código deste tutorial que você pode encontrar [aqui](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website).** - -**Mais documentação sobre `Waffle` disponível [aqui](https://getwaffle.io).** diff --git a/public/content/translations/pt-br/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/pt-br/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 651f49afe6a..00000000000 --- a/public/content/translations/pt-br/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: "Waffle: simulações dinâmicas e testando chamadas de contrato" -description: Tutorial avançado de Waffle para usar simulação dinâmica e testar chamadas contratuais -author: "Daniel Izdebski" -tags: - - "waffle" - - "Contratos Inteligentes" - - "solidity" - - "Testes" - - "simulando" -skill: intermediate -lang: pt-br -published: 2020-11-14 ---- - -## Do que se trata esse tutorial? {#what-is-this-tutorial-about} - -Neste tutorial, você aprenderá: - -- use simulação dinâmica -- testar interações entre contratos inteligentes - -Pressupostos: - -- você já sabe como escrever um contrato inteligente simples em `Solidity` -- você conhece o seu `JavaScript` e `TypeScript` -- você fez outros `tutoriais` do Waffle ou sabe alguma coisa sobre isso - -## Simulação dinâmica {#dynamic-mocking} - -Por que a simulação dinâmica é útil? Bem, isso permite-nos escrever testes unitários em vez de testes de integração. O que isso significa? Isso significa que não precisamos nos preocupar com as dependências dos contratos inteligentes, assim podemos testar todos eles em total isolamento. Deixe-me te mostrar como exatamente você pode fazer isso. - -### **1. Projeto** {#1-project} - -Antes de começar, precisamos preparar um projeto simples no node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -Vamos começar adicionando typescript e testes de dependências - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Agora vamos adicionar `Waffle` e `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -A nossa estrutura de projetos deverá ficar assim: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Contrato inteligente** {#2-smart-contract} - -Para iniciar uma simulação dinâmica, precisamos de um contrato inteligente com dependências. Não se preocupe, nós ajudamos você! - -Aqui está um simples contrato inteligente escrito na `Solidity` cujo único objetivo é conferir se somos ricos. Ele usa o token ERC20 para verificar se temos tokens suficientes. Coloque em `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Como queremos usar simulação dinâmica, não precisamos de todo o ERC20, é por isso que estamos usando a interface IERC20 com apenas uma função. - -É hora de construir este contrato! Para isso, usaremos o `Waffle`. Primeiro, vamos criar um arquivo de configuração simples `waffle.json` que especifica as opções de compilação. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Agora estamos prontos para construir o contrato com Waffle: - -```bash -npx waffle -``` - -Fácil, certo? Na pasta `de compilação/` dois arquivos correspondentes ao contrato e a interface apareceu. Nós os utilizaremos mais tarde para testar. - -### **3. Testando** {#3-testing} - -Vamos criar um arquivo chamado `AmIRichAlready.test.ts` para os testes reais. Em primeiro lugar, temos de lidar com as importações. Nós precisaremos deles para mais tarde: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Exceto para dependências JS, precisamos importar nossa interface e contrato construídos: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle usa `chai` para testes. No entanto, antes de podermos usá-lo, temos que injetar os "matchers" de Waffle em si mesmo: - -```typescript -use(solidity) -``` - -Precisamos implementar a função `beforeEach()` que irá redefinir o estado do contrato antes de cada teste. Primeiro, vamos pensar no que precisamos lá. Para implantar um contrato, precisamos de duas coisas: uma carteira e um contrato ERC20 implementado para passá-la como um argumento para o contrato `AmIRichalready`. - -Em primeiro lugar, criamos uma carteira: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Depois, precisamos de implantar um contrato do ERC20. Aqui está a parte complicada - nós temos apenas uma interface. Esta é a parte em que Waffle vem nos salvar. Waffle tem uma função mágica `deployMockContract()` que cria um contrato usando apenas o _abi_ da interface: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Agora com a carteira e o ERC20 implantados, podemos ir em frente e implantar o contrato `AmIRichalready` (Contrato: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Com tudo isso, nossa função `beforeEach()` está terminada. Até agora o seu arquivo `AmIRichAlready.test.ts` deve se parecer com isto: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Vamos fazer o primeiro teste para o contrato `AmIRichalready`. Sobre o que acha que o nosso teste deveria ser? Sim, você tem razão! Deveríamos verificar se já somos ricos :) - -Um, pera um segundo. Como o nosso contrato simulado saberá quais valores retornar? Não implementamos nenhuma lógica para a função `balanceOf()`. Mais uma vez, Waffle pode ajudar aqui. Nosso contrato simulado tem algumas coisas novas e bonitas agora: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Com esse conhecimento, podemos finalmente escrever nosso primeiro teste: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Vamos travar esse teste em partes: - -1. Definimos nosso contrato simulado no ERC20 para sempre devolver o saldo de tokens de 9999999999. -2. Verifique se o método `contract.check()` retorna `false`. - -Nós estamos prontos para disparar a fera: - -![Um test passando](test-one.png) - -Então o teste funciona, mas... ainda há espaço para melhorias. A função `saldoOf()` sempre retornará 99999. Podemos melhorá-la especificando uma carteira para a qual a função deve retornar algo - como um contrato de verdade: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Até agora, nós testamos apenas o caso em que não estamos ricos o suficiente. Em vez disso, vamos testar o oposto: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Você executa os testes... - -![Dois testes passando](test-two.png) - -E aqui está você! Nosso contrato parece funcionar como pretendido :) - -## Testando chamadas de contrato {#testing-contract-calls} - -Vamos resumir o que fez até agora. Nós testamos a funcionalidade do nosso contrato de `AmIRichalready` e parece que ele está funcionando corretamente. Isso significa que estamos prontos, né? Não exatamente! Waffle permite-nos testar ainda mais o nosso contrato. Mas o quanto exatamente? Bem, no arsenal de Waffle há um `calledOnContract()` e `calledOnContractWith()` correspondentes. Eles nos permitirão verificar se nosso contrato chamado de simulação (mock, em inglês) do ERC20. Aqui está um teste básico com um desses matchers: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Podemos ir ainda mais longe e melhorar este teste com o outro "matcher" que eu te falei: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Vamos verificar se os testes estão corretos: - -![Três testes passando](test-three.png) - -Ótimo, todos os testes são verdes. - -Testar chamadas de contrato com Waffle é super fácil. E aqui está a melhor parte. Esses "matchers" trabalham com contratos normais e simulados! É porque o Waffle registra e filtra chamadas EVM em vez de injetar código, como é no caso de bibliotecas de teste populares de outras tecnologias. - -## A Linha de Chegada {#the-finish-line} - -Parabéns! Agora você sabe como usar Waffle para testar chamadas de contrato e contratos simulados dinamicamente. Há características muito mais interessantes para descobrir. Recomendo mergulhar na documentação do Waffle. - -A documentação do Waffle está disponível [aqui](https://ethereum-waffle.readthedocs.io/). - -O código fonte deste tutorial pode ser encontrado [aqui](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Você pode também estar interessado em: - -- [Testando contratos inteligentes com Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/pt-br/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/pt-br/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 851cb979840..00000000000 --- a/public/content/translations/pt-br/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: "Tutorial Waffle diz hello world com hardhat e ethers" -description: Faça seu primeiro projeto Waffle com hardhat e ethers.js -author: "MiZiet" -tags: - - "waffle" - - "contratos inteligentes" - - "solidity" - - "testando" - - "hardhat" - - "ethers.js" -skill: intermediate -lang: pt-br -published: 2020-10-16 ---- - -Neste [tutorial do Waffle](https://ethereum-waffle.readthedocs.io), aprenderemos como criar um simples projeto de contrato inteligente "Hello world", usando [hardhat](https://hardhat.org/) e [ethers. s](https://docs.ethers.io/v5/). Em seguida, aprenderemos como adicionar uma nova funcionalidade ao nosso contrato inteligente e como testá-lo com Waffle. - -Vamos começar criando um novo projeto: - -```bash -yarn init -``` - -ou - -```bash -npm init -``` - -e instalando os pacotes necessários: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -ou - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -O próximo passo é criar um projeto hardhat de amostra, executando `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? O que você deseja fazer? … -★ Crie um projeto de exemplo -Crie um hardhat.config.js vazio -Saia -``` - -Selecione `Create a sample project` - -A nossa estrutura de projetos deverá ficar assim: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributs -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Agora vamos falar sobre alguns desses arquivos: {#now-lets-talk} - -- Greeter.sol - nosso smart contract escrito em Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Nosso contrato inteligente pode ser dividido em três partes: - -1. constructor - onde declaramos uma variável de tipo string chamada `greeting`, -2. function greet - função que retornará `greeting` quando chamada, -3. function setGreeting - uma função que nos permite alterar o valor da função `greeting`. - -- sample-test.js - nosso arquivo de testes - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### O próximo passo consiste em compilar nosso contrato e executar testes: {#compiling-and-testing} - -Testes de Waffle usam Mocha (um framework de teste) com Chai (uma biblioteca de asserção). Tudo o que você precisa fazer é executar `npx hardhat test` e esperar que a seguinte mensagem apareça. - -```bash -✓ Deve retornar a nova saudação uma vez alterada -``` - -### Tudo parece ótimo até agora, vamos adicionar mais complexidade ao nosso projeto {#adding-complexity} - -Imagine uma situação quando alguém adiciona uma string vazia como saudação. Não seria uma saudação calorosa, né? -Vamos nos certicar que isso não aconteça: - -Queremos usar o `revert` do Solidity quando alguém passar uma string vazia. Uma coisa boa é que podemos facilmente testar esta funcionalidade com o chai matcher do Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Parece que o nosso novo teste não passou: - -```bash -Implantando um Greeter com saudação: Olá, mundo! -Mude de saudação de 'Hello, world!' para 'Hola, mundo!' - ✓ Deve devolver a nova saudação uma vez que ela tenha sido alterada (1514ms) -Implantando um Greeter com saudação: Olá, mundo! -Mudar saudação de 'Olá, mundo!' para '' - 1) Deve reverter quando passar uma seqüência vazia - - - 1 passagem (2s) - 1 falhando -``` - -Vamos implementar esta funcionalidade em nosso contrato inteligente: - -```solidity -require(bytes(_greeting).length > 0, "Greeting message is empty"); -``` - -Agora, nossa função setGreeting se parece com isso: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Vamos executar os testes novamente: - -```bash -✓ Deve retornar a nova saudação quando ela for alterada (1467ms) -✓ Deve reverter quando passar uma string vazia (276ms) - -2 passagem (2s) -``` - -Parabéns! Você terminou :) - -### Conclusão {#conclusion} - -Fizemos um projeto simples com Waffle, Hardhat e ethers.js. Aprendemos como criar um projeto, adicionar um teste e implementar novas funcionalidades. - -Para mais combinações excelentes de chai para testar seus smart contracts, confira a [documentação oficial da Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/pt-br/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/pt-br/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index b3038f8108b..00000000000 --- a/public/content/translations/pt-br/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Testando um contrato inteligente simples com a biblioteca Waffle -description: Tutorial para iniciantes -author: Ewa Kowalska -tags: - - "contratos inteligentes" - - "solidity" - - "Waffle" - - "testando" -skill: intermediate -lang: pt-br -published: 2021-02-26 ---- - -## Neste tutorial, você aprenderá como {#in-this-tutorial-youll-learn-how-to} - -- Testar as mudanças do saldo da carteira -- Testar a emissão de eventos com argumentos especificados -- Assegurar que uma transação foi revertida - -## Suposições {#assumptions} - -- Você pode criar um novo projeto JavaScript ou TypeScript -- Você tem alguma experiência básica com testes em JavaScript -- Você tem usado gerenciadores de pacotes como Yarn ou NPM -- Você possui um conhecimento muito básico de contratos inteligentes e Solidity - -## Introdução {#getting-started} - -O tutorial demonstra a configuração do teste e a execução usando yarn, mas não há problema se você preferir npm - Eu fornecerei referências adequadas a [documentação](https://ethereum-waffle.readthedocs.io/en/latest/index.html) oficial do Waffle. - -### Instalando Dependências {#install-dependencies} - -[Adicione](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) as dependências do ethereum-waffle e typescript às dependências de desenvolvimento do seu projeto. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -### Exemplo de contrato inteligente {#example-smart-contract} - -Durante o tutorial, nós trabalharemos em um exemplo de contrato inteligente simples - EtherSplitter. Não faz nada de mais, além de permitir que qualquer um envie somas em wei e divida-as igualmente entre dois destinatários predefinidos. A função split exige que a quantidade de wei seja par, caso contrário, ela será anulada. Para ambos os destinatários, ela realiza uma transferência em wei, seguido da emissão do evento Transferir. - -Coloque o trecho de código EtherSplitter em `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -### Compilar o contrato {#compile-the-contract} - -Para [compilar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) o contrato, adicione a seguinte entrada ao arquivo package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Em seguida, crie o arquivo de configuração do Waffle, no diretório raiz do projeto - `waffle.json` - e então cole a seguinte configuração lá: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Execute `yarn build`. Como resultado, o diretório `build` aparecerá com o contrato compilado, EtherSplitter, no formato JSON. - -### Teste de configuração {#test-setup} - -Testar com Waffle requer usar os matchers (comparadores) Chai e Mocha, então você precisa [adicionar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) ao seu projeto. Atualize seu arquivo package.json e adicione a entrada `test` na parte de scripts: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Se você quiser [executar](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) seus testes, basta executar `yarn test`. - -## Testando {#testing} - -Agora crie o diretório `test` e crie o novo arquivo `test\EtherSplitter.test.ts`. Copie o trecho de código abaixo e cole-o em nosso arquivo de teste. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -Algumas palavras antes de começarmos. O `MockProvider` vem com uma versão em mock (simulada de um objeto real) da blockchain. Ele também fornece o mock de carteiras que nos servirão para testar o contrato EtherSplitter. Podemos obter até dez carteiras chamando o método `getWallets()` no provedor. No exemplo, nós obtemos três carteiras - para o remetente e duas para os destinatários. - -Em seguida, declaramos uma variável chamada 'splitter' - este é o nosso contrato mock EtherSplitter. Ele é criado antes de cada execução de um único teste pelo método `deployContract`. Este método simula a implantação de um contrato, da carteira passada como primeiro parâmetro (a carteira do remetente em nosso caso). O segundo parâmetro é a ABI e o bytecode do contrato testado — passamos para lá o arquivo json do contrato EtherSplitter compilado no diretório `build`. O terceiro parâmetro é uma matriz com os argumentos do construtor do contrato que, no nosso caso, são os dois endereços dos destinatários. - -### changeBalances {#changebalances} - -Primeiro, verificaremos se o método split realmente altera os saldos das carteiras dos destinatários. Se dividirmos 50 wei da conta do remetente, nós esperaríamos que os saldos de ambos os destinatários aumentassem em 25 wei. Nós usaremos o matcher `changeBalances` do Waffle: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Como o primeiro parâmetro do matcher, nós passamos um array de carteiras dos destinatários e, como segundo - um array de aumentos esperados nas contas correspondentes. Se nós quiséssemos verificar o saldo de uma carteira específica, também poderíamos usar o matcher `changeBalance`, que não requer a passagem de arrays, como no exemplo abaixo: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Observe que, em ambos os casos de `changeBalance` e de `changeBalances`, transmitimos a função split como um retorno de chamada, pois o comparador precisa acessar o estado dos saldos antes e depois da chamada. - -A seguir, testaremos se o evento Transfer foi emitido após cada transferência de wei. Vamos passar para outro comparador do Waffle: - -### Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -O matcher `emit` nos permite verificar, se um contrato emitiu um evento ao chamar um método. Como parâmetros para o matcher `emit`, nós fornecemos o mock do contrato, que prevemos para emitir o evento, juntamente com o nome desse evento. Em nosso caso, o contrato simulado é o `splitter` e o nome do evento é `Transfer`. Nós também podemos verificar os valores precisos dos argumentos, com os quais o evento foi emitido - nós passamos tantos argumentos para o matcher `withArgs`, como espera a nossa declaração de evento. No caso do contrato EtherSplitter, passamos os endereços do remetente e do destinatário, juntamente com a quantia de wei transferida. - -### revertedWith {#revertedwith} - -Como último exemplo, nós verificaremos se a transação foi revertida, em caso de número desigual de wei. Usaremos o matcher `revertedWith`: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -O teste, se aprovado, nos garantirá que a transação foi revertida de fato. No entanto, também deve haver uma correspondência exata entre as mensagens que passamos, na instrução `require` e a mensagem que esperamos em `revertedWith`. Se voltarmos ao código do contrato EtherSplitter, na declaração `require` para a quantidade wei, fornecemos a mensagem: 'Quantidade de wei desigual não permitida'. Isso corresponde à mensagem que esperamos em nosso teste. Se eles não fossem iguais, o teste falharia. - -## Parabéns! {#congratulations} - -Você acabou de dar seu primeiro grande passo para testar contratos inteligentes com Waffle! diff --git a/public/content/translations/sw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/sw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index c130edb8393..00000000000 --- a/public/content/translations/sw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: Uigaji unaobadilika na kupima wito wa mkataba" -description: Mafunzo ya kina ya Waffle kwa kutumia uigaji unaobadilika na kupima wito wa mkataba -author: "Daniel Izdebski" -tags: - [ - "waffle", - "mikataba erevu", - "uimara", - "majaribio", - "kuiga" - ] -skill: intermediate -lang: sw -published: 2020-11-14 ---- - -## Mafunzo haya yanahusu nini? {#what-is-this-tutorial-about} - -Katika mafunzo haya utajifunza jinsi ya: - -- kutumia uigaji unaobadilika -- kupima mwingiliano kati ya mikataba-erevu - -Mawazo: - -- tayari unajua jinsi ya kuandika mkataba-erevu rahisi katika `Solidity` -- unafahamu vizuri `JavaScript` na `TypeScript` -- umefanya mafunzo mengine ya `Waffle` au unajua kitu kimoja au viwili kuihusu - -## Uigaji unaobadilika {#dynamic-mocking} - -Kwa nini uigaji unaobadilika ni muhimu? Naam, inaturuhusu kuandika majaribio ya kitengo badala ya majaribio ya ujumuishaji. Hii inamaanisha nini? Inamaanisha kuwa hatuhitaji kuwa na wasiwasi kuhusu utegemezi wa mikataba-erevu, hivyo tunaweza kupima zote kwa kujitenga kabisa. Acha nikuonyeshe jinsi unavyoweza kufanya hivyo. - -### **1. Mradi** {#1-project} - -Kabla hatujaanza tunahitaji kuandaa mradi rahisi wa node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# au kama unatumia npm -npm init -``` - -Tuanze kwa kuongeza typescript na tegemezi za majaribio - mocha & chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# au kama unatumia npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Sasa tuongeze `Waffle` na `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# au kama unatumia npm -npm install ethereum-waffle ethers --save-dev -``` - -Muundo wa mradi wako unapaswa kuonekana hivi sasa: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Mkataba-erevu** {#2-smart-contract} - -Ili kuanza uigaji unaobadilika, tunahitaji mkataba-erevu wenye utegemezi. Usijali, nimekusaidia! - -Huu hapa ni mkataba-erevu rahisi ulioandikwa kwa `Solidity` ambao lengo lake pekee ni kuangalia kama sisi ni matajiri. Inatumia tokeni ya ERC20 kuangalia kama tuna tokeni za kutosha. Weka katika `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Kwa vile tunataka kutumia uigaji unaobadilika hatuhitaji ERC20 nzima, ndiyo maana tunatumia kiolesura cha IERC20 chenye chaguo moja la kukokotoa. - -Ni wakati wa kujenga mkataba huu! Kwa ajili hiyo tutatumia `Waffle`. Kwanza, tutaenda kuunda faili rahisi ya usanidi ya `waffle.json` inayobainisha chaguo za ujenzi. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Sasa tuko tayari kujenga mkataba kwa kutumia Waffle: - -```bash -npx waffle -``` - -Rahisi, sivyo? Katika folda ya `build/` faili mbili zinazolingana na mkataba na kiolesura zimeonekana. Tutazitumia baadaye kwa ajili ya majaribio. - -### **3. Kupima** {#3-testing} - -Tuunde faili inayoitwa `AmIRichAlready.test.ts` kwa ajili ya majaribio halisi. Kwanza kabisa, tunapaswa kushughulikia uingizaji. Tutazihitaji baadaye: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Isipokuwa tegemezi za JS, tunahitaji kuingiza mkataba wetu uliojengwa na kiolesura: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle hutumia `chai` kwa ajili ya majaribio. Hata hivyo, kabla hatujaweza kuitumia, tunapaswa kuingiza vilinganishi vya Waffle ndani ya chai yenyewe: - -```typescript -use(solidity) -``` - -Tunahitaji kutekeleza chaguo la kukokotoa la `beforeEach()` litaloweka upya hali ya mkataba kabla ya kila jaribio. Tufikirie kwanza kile tunachohitaji hapo. Ili kupeleka mkataba tunahitaji vitu viwili: mkoba na mkataba wa ERC20 uliotumwa ili kuupitisha kama hoja kwa mkataba wa `AmIRichAlready`. - -Kwanza tunatengeneza mkoba: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Kisha tunahitaji kupeleka mkataba wa ERC20. Hapa ndipo penye ugumu - tuna kiolesura pekee. Hapa ndipo Waffle inakuja kutuokoa. Waffle ina chaguo la kukokotoa la kimiujiza la `deployMockContract()` linalounda mkataba kwa kutumia _abi_ ya kiolesura pekee: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Sasa tukiwa na mkoba na ERC20 iliyopelekwa, tunaweza kuendelea na kupeleka mkataba wa `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Kwa hayo yote, chaguo letu la kukokotoa la `beforeEach()` limekamilika. Hadi sasa faili lako la `AmIRichAlready.test.ts` linapaswa kuonekana hivi: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Tuandike jaribio la kwanza kwa mkataba wa `AmIRichAlready`. Unafikiri jaribio letu linapaswa kuwa kuhusu nini? Ndio, uko sahihi! Tunapaswa kuangalia ikiwa tayari sisi ni matajiri :) - -Lakini subiri kidogo. Mkataba wetu ulioigwa utajuaje thamani zipi za kurudisha? Hatujatekeleza mantiki yoyote kwa chaguo la kukokotoa la `balanceOf()`. Tena, Waffle inaweza kusaidia hapa. Mkataba wetu ulioigwa una mambo mapya ya kuvutia sasa: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Kwa ujuzi huu hatimaye tunaweza kuandika jaribio letu la kwanza: - -```typescript -it("hurudisha uongo ikiwa mkoba una tokeni chini ya 1000000", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Tugawanye jaribio hili katika sehemu: - -1. Tunaweka mkataba wetu wa kuiga wa ERC20 kurudisha salio la tokeni 999999 kila wakati. -2. Angalia kama njia ya `contract.check()` inarudisha `uongo`. - -Tuko tayari kuanzisha mambo: - -![Jaribio moja limefaulu](./test-one.png) - -Kwa hiyo jaribio linafanya kazi, lakini... bado kuna nafasi ya kuboresha. Chaguo la kukokotoa la `balanceOf()` litarudisha 999999 kila wakati. Tunaweza kuiboresha kwa kubainisha mkoba ambayo chaguo la kukokotoa linapaswa kurudisha kitu - kama mkataba halisi: - -```typescript -it("hurudisha uongo ikiwa mkoba una tokeni chini ya 1000001", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Hadi sasa, tumejaribu tu kisa ambapo hatuna utajiri wa kutosha. Badala yake, tupime kinyume chake: - -```typescript -it("hurudisha kweli ikiwa mkoba una angalau tokeni 1000001", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Unaendesha majaribio... - -![Majaribio mawili yamefaulu](test-two.png) - -...na umefika! Mkataba wetu unaonekana kufanya kazi kama ilivyokusudiwa :) - -## Kupima wito wa mkataba {#testing-contract-calls} - -Tufanye muhtasari wa kile tumefanya hadi sasa. Tumepima utendaji wa mkataba wetu wa `AmIRichAlready` na unaonekana kufanya kazi ipasavyo. Hiyo inamaanisha tumemaliza, sivyo? Sio kabisa! Waffle inaturuhusu kupima mkataba wetu hata zaidi. Lakini vipi hasa? Naam, katika safu ya Waffle kuna vilinganishi vya `calledOnContract()` na `calledOnContractWith()`. Vitatruhusu kuangalia ikiwa mkataba wetu uliita mkataba wa kuiga wa ERC20. Hili hapa ni jaribio la msingi na kimoja cha vilinganishi hivi: - -```typescript -it("huangalia ikiwa mkataba uliita balanceOf kwenye tokeni ya ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Tunaweza kwenda mbali zaidi na kuboresha jaribio hili kwa kilinganishi kingine nilichokuambia: - -```typescript -it("huangalia ikiwa mkataba uliita balanceOf na mkoba fulani kwenye tokeni ya ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Hebu tuangalie kama majaribio ni sahihi: - -![Majaribio matatu yamefaulu](test-three.png) - -Safi sana, majaribio yote yamefaulu. - -Kupima wito wa mkataba kwa Waffle ni rahisi sana. Na hapa ndipo sehemu bora zaidi. Vilinganishi hivi hufanya kazi na mikataba ya kawaida na iliyoigwa! Hii ni kwa sababu Waffle hurekodi na kuchuja wito za EVM badala ya kuingiza msimbo, kama ilivyo kwa maktaba maarufu za majaribio kwa teknolojia nyingine. - -## Mstari wa Mwisho {#the-finish-line} - -Hongera! Sasa unajua jinsi ya kutumia Waffle kupima wito wa mkataba na kuiga mikataba kwa ubadilikaji. Kuna vipengele vingi zaidi vya kuvutia vya kugundua. Ninapendekeza kuzama katika nyaraka za Waffle. - -Nyaraka za Waffle zinapatikana [hapa](https://ethereum-waffle.readthedocs.io/). - -Msimbo chanzo wa mafunzo haya unapatikana [hapa](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Mafunzo ambayo unaweza kupendezwa nayo pia: - -- [Kupima mikataba-erevu na Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/sw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/sw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index e112d021c26..00000000000 --- a/public/content/translations/sw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Mafunzo ya Waffle ya kusema hello world kwa kutumia hardhat na ethers" -description: Tengeneza mradi wako wa kwanza wa Waffle kwa kutumia hardhat na ethers.js -author: "MiZiet" -tags: - [ - "waffle", - "mikataba erevu", - "uimara", - "majaribio", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: sw -published: 2020-10-16 ---- - -Katika mafunzo haya ya [Waffle](https://ethereum-waffle.readthedocs.io), tutajifunza jinsi ya kuweka mradi rahisi wa mkataba-erevu wa "Hello world", kwa kutumia [hardhat](https://hardhat.org/) na [ethers.js](https://docs.ethers.io/v5/). Kisha tutajifunza jinsi ya kuongeza utendaji mpya kwenye mkataba-erevu wetu na jinsi ya kuujaribu kwa kutumia Waffle. - -Wacha tuanze kwa kuunda mradi mpya: - -```bash -yarn init -``` - -au - -```bash -npm init -``` - -na kusakinisha vifurushi vinavyohitajika: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -au - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Hatua inayofuata ni kuunda mradi wa sampuli wa hardhat kwa kutumia `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -Chagua `Create a sample project` - -Muundo wa mradi wetu unapaswa kuonekana kama hivi: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Sasa hebu tuzungumzie baadhi ya faili hizi: {#now-lets-talk} - -- Greeter.sol - mkataba-erevu wetu ulioandikwa kwa solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Mkataba-erevu wetu unaweza kugawanywa katika sehemu tatu: - -1. constructor - ambapo tunatangaza kigezo cha aina ya string kinachoitwa `greeting`, -2. function greet - kazi ambayo itarudisha `greeting` inapoitwa, -3. function setGreeting - kazi inayoturuhusu kubadilisha thamani ya `greeting`. - -- sample-test.js - faili yetu ya majaribio - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Hatua inayofuata inajumuisha kuandaa mkataba wetu na kuendesha majaribio: {#compiling-and-testing} - -Majaribio ya Waffle hutumia Mocha (mfumo wa majaribio) na Chai (maktaba ya uhakikisho). Unachotakiwa kufanya ni kuendesha `npx hardhat test` na kusubiri ujumbe ufuatao uonekane. - -```bash -✓ Should return the new greeting once it's changed -``` - -### Kila kitu kinaonekana vizuri hadi sasa, hebu tuongeze utata zaidi kwenye mradi wetu {#adding-complexity} - -Fikiria hali ambapo mtu anaongeza string tupu kama salamu. Hiyo haitakuwa salamu ya ukarimu, sawa? -Wacha tuhakikishe hilo halitokei: - -Tunataka kutumia `revert` ya solidity mtu anapopitisha string tupu. Jambo zuri ni kwamba tunaweza kujaribu utendaji huu kwa urahisi na kilinganishi cha chai cha Waffle `to.be.revertedWith()`. - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -Inaonekana jaribio letu jipya halikufaulu: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -Wacha tutekeleze utendaji huu katika mkataba-erevu wetu: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -Sasa, kazi yetu ya setGreeting inaonekana hivi: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Wacha tuendeshe majaribio tena: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -Hongera! Umefaulu :) - -### Hitimisho {#conclusion} - -Tulitengeneza mradi rahisi kwa Waffle, Hardhat na ethers.js. Tulijifunza jinsi ya kuweka mradi, kuongeza jaribio na kutekeleza utendaji mpya. - -Kwa vilinganishi bora zaidi vya chai vya kujaribu mikataba-erevu yako, angalia [hati rasmi za Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/sw/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/sw/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 24233e3b5ec..00000000000 --- a/public/content/translations/sw/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Kujaribu mkataba-erevu rahisi kwa kutumia maktaba ya Waffle -description: Mafunzo kwa wanaoanza -author: Ewa Kowalska -tags: [ "mikataba erevu", "uimara", "Waffle", "majaribio" ] -skill: beginner -lang: sw -published: 2021-02-26 ---- - -## Katika mafunzo haya utajifunza jinsi ya {#in-this-tutorial-youll-learn-how-to} - -- Jaribu mabadiliko ya salio la mkoba -- Jaribu utoaji wa matukio na hoja maalum -- Thibitisha kuwa muamala ulirejeshwa - -## Dhana {#assumptions} - -- Unaweza kuunda mradi mpya wa JavaScript au TypeScript -- Una uzoefu wa kimsingi na majaribio katika JavaScript -- Umetumia wasimamizi wengine wa vifurushi kama vile yarn au npm -- Una ufahamu wa kimsingi sana wa mikataba-erevu na Solidity - -## Kuanza {#getting-started} - -Mafunzo haya yanaonyesha usanidi na uendeshaji wa jaribio kwa kutumia yarn, lakini hakuna shida ikiwa unapendelea npm - nitatoa marejeleo sahihi kwa [nyaraka](https://ethereum-waffle.readthedocs.io/en/latest/index.html) rasmi za Waffle. - -## Sakinisha Vitegemezi {#install-dependencies} - -[Ongeza](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) vitegemezi vya ethereum-waffle na typescript kwenye vitegemezi vya dev vya mradi wako. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Mfano wa mkataba-erevu {#example-smart-contract} - -Wakati wa mafunzo haya tutafanyia kazi mfano rahisi wa mkataba-erevu - EtherSplitter. Haufanyi mengi isipokuwa kuruhusu mtu yeyote kutuma wei fulani na kuigawanya sawasawa kati ya wapokeaji wawili waliobainishwa awali. -Kitendaji cha kugawanya kinahitaji namba ya wei iwe shufwa, vinginevyo kitarejeshwa. Kwa wapokeaji wote wawili hufanya uhamisho wa wei ikifuatiwa na utoaji wa tukio la Uhamisho. - -Weka kipande cha msimbo wa EtherSplitter katika `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Kusanya mkataba {#compile-the-contract} - -Ili [kukusanya](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) mkataba ongeza ingizo lifuatalo kwenye faili la package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Ifuatayo, unda faili la usanidi la Waffle katika saraka kuu ya mradi - `waffle.json` - na kisha ubandike usanidi ufuatao hapo: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Endesha `yarn build`. Kama matokeo, saraka ya `build` itaonekana na mkataba wa EtherSplitter uliokusanywa katika muundo wa JSON. - -## Usanidi wa Jaribio {#test-setup} - -Kujaribu na Waffle kunahitaji kutumia vilinganishi vya Chai na Mocha, kwa hivyo unahitaji [kuwaongeza](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) kwenye mradi wako. Sasisha faili yako ya package.json na ongeza ingizo la `test` katika sehemu ya scripts: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Ikiwa unataka [kutekeleza](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) majaribio yako, endesha tu `yarn test` . - -## Kujaribu {#testing} - -Sasa unda saraka ya `test` na unda faili mpya `test\EtherSplitter.test.ts`. -Nakili kipande kilicho hapa chini na ukibandike kwenye faili letu la majaribio. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -Maneno machache kabla ya kuanza. -`MockProvider` huja na toleo la mfano la mnyororo wa bloku. Pia hutoa mikoba ya mfano ambayo itatusaidia kwa kujaribu mkataba wa EtherSplitter. Tunaweza kupata hadi mikoba kumi kwa kuita mbinu ya `getWallets()` kwenye mtoa huduma. Katika mfano, tunapata mikoba mitatu - kwa mtumaji na kwa wapokeaji wawili. - -Ifuatayo, tunatangaza kigezo kinachoitwa 'splitter' - huu ni mkataba wetu wa mfano wa EtherSplitter. Inaundwa kabla ya kila utekelezaji wa jaribio moja kwa mbinu ya `deployContract`. Mbinu hii inaiga upelekaji wa mkataba kutoka kwenye mkoba uliopitishwa kama kigezo cha kwanza (mkoba wa mtumaji katika kesi yetu). Kigezo cha pili ni ABI na bytecode ya mkataba unaojaribiwa - tunapitisha hapo faili la json la mkataba wa EtherSplitter uliokusanywa kutoka kwenye saraka ya `build`. Kigezo cha tatu ni safu yenye hoja za kiunda mkataba, ambazo katika kesi yetu, ni anwani mbili za wapokeaji. - -## changeBalances {#changebalances} - -Kwanza, tutaangalia ikiwa mbinu ya kugawanya inabadilisha salio kweli la mikoba ya wapokeaji. Ikiwa tutagawanya wei 50 kutoka kwa akaunti ya mtumaji, tutarajia salio la wapokeaji wote wawili kuongezeka kwa wei 25. Tutatumia kilinganishi cha `changeBalances` cha Waffle: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Kama kigezo cha kwanza cha kilinganishi, tunapitisha safu ya mikoba ya wapokeaji, na kama ya pili - safu ya ongezeko linalotarajiwa kwenye akaunti husika. -Ikiwa tungetaka kuangalia salio la mkoba mmoja maalum, tungeweza pia kutumia kilinganishi cha `changeBalance`, ambacho hakihitaji kupitisha safu, kama katika mfano hapa chini: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Kumbuka kuwa katika visa vyote viwili vya `changeBalance` na `changeBalances` tunapitisha kitendaji cha kugawanya kama simurejeshi kwa sababu kilinganishi kinahitaji kufikia hali ya salio kabla na baada ya wito. - -Ifuatayo, tutajaribu ikiwa tukio la Uhamisho lilitolewa baada ya kila uhamisho wa wei. Tutaelekea kwenye kilinganishi kingine kutoka Waffle: - -## Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -Kilinganishi cha `emit` kinaturuhusu kuangalia ikiwa mkataba ulitoa tukio wakati wa kuita mbinu. Kama vigezo vya kilinganishi cha `emit`, tunatoa mkataba wa mfano ambao tunatabiri utatoa tukio, pamoja na jina la tukio hilo. Katika kesi yetu, mkataba wa mfano ni `splitter` na jina la tukio - `Transfer`. Tunaweza pia kuthibitisha thamani kamili za hoja ambazo tukio lilitolewa nazo - tunapitisha hoja nyingi kwenye kilinganishi cha `withArgs`, kama tamko letu la tukio linavyotarajia. Katika kesi ya mkataba wa EtherSplitter, tunapitisha anwani za mtumaji na mpokeaji pamoja na kiasi cha wei kilichohamishwa. - -## revertedWith {#revertedwith} - -Kama mfano wa mwisho, tutaangalia ikiwa muamala ulirejeshwa ikiwa nambari ya wei si shufwa. Tutatumia kilinganishi cha `revertedWith`: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -Jaribio, likifaulu, litatuhakikishia kwamba muamala ulirejeshwa kweli. Hata hivyo, lazima pia kuwe na mlingano kamili kati ya ujumbe tuliouweka katika taarifa ya `require` na ujumbe tunaotarajia katika `revertedWith`. Tukirudi kwenye msimbo wa mkataba wa EtherSplitter, katika taarifa ya `require` kwa kiasi cha wei, tunatoa ujumbe: 'Uneven wei amount not allowed'. Huu unalingana na ujumbe tunaotarajia katika jaribio letu. Kama hazingekuwa sawa, jaribio lingefeli. - -## Hongera! {#congratulations} - -Umechukua hatua yako kubwa ya kwanza kuelekea kujaribu mikataba-erevu na Waffle! diff --git a/public/content/translations/te/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/te/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index f66de418ddd..00000000000 --- a/public/content/translations/te/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "వాఫిల్: డైనమిక్ మాకింగ్ మరియు కాంట్రాక్ట్ కాల్స్‌ను పరీక్షించడం" -description: "డైనమిక్ మాకింగ్ మరియు కాంట్రాక్ట్ కాల్స్ పరీక్షించడం కోసం అధునాతన వాఫిల్ ట్యుటోరియల్" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "స్మార్ట్ కాంట్రాక్టులు", - "దృఢత్వం", - "పరీక్షించడం", - "మాకింగ్" - ] -skill: intermediate -lang: te -published: 2020-11-14 ---- - -## ఈ ట్యుటోరియల్ దేని గురించి? {#what-is-this-tutorial-about} - -ఈ ట్యుటోరియల్‌లో మీరు వీటిని ఎలా చేయాలో నేర్చుకుంటారు: - -- డైనమిక్ మాకింగ్‌ను ఉపయోగించండి -- స్మార్ట్ కాంట్రాక్టుల మధ్య పరస్పర చర్యలను పరీక్షించండి - -అంచనాలు: - -- `Solidity`లో ఒక సాధారణ స్మార్ట్ కాంట్రాక్ట్‌ను ఎలా వ్రాయాలో మీకు ఇప్పటికే తెలుసు -- `JavaScript` మరియు `TypeScript` గురించి మీకు బాగా తెలుసు -- మీరు ఇతర `Waffle` ట్యుటోరియల్స్ చేసారు లేదా దాని గురించి ఒకటి రెండు విషయాలు తెలుసు - -## డైనమిక్ మాకింగ్ {#dynamic-mocking} - -డైనమిక్ మాకింగ్ ఎందుకు ఉపయోగపడుతుంది? సరే, ఇది ఇంటిగ్రేషన్ టెస్ట్‌లకు బదులుగా యూనిట్ టెస్ట్‌లను వ్రాయడానికి మమ్మల్ని అనుమతిస్తుంది. దాని అర్థం ఏమిటి? దీని అర్థం మనం స్మార్ట్ కాంట్రాక్టుల డిపెండెన్సీల గురించి ఆందోళన చెందాల్సిన అవసరం లేదు, తద్వారా వాటన్నింటినీ పూర్తి ఏకాంతంలో పరీక్షించవచ్చు. మీరు దానిని ఖచ్చితంగా ఎలా చేయగలరో నేను మీకు చూపిస్తాను. - -### **1. ప్రాజెక్ట్** {#1-project} - -మేము ప్రారంభించడానికి ముందు ఒక సాధారణ node.js ప్రాజెక్ట్‌ను సిద్ధం చేయాలి: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# లేదా మీరు npm వాడుతుంటే -npm init -``` - -టైప్‌స్క్రిప్ట్ మరియు టెస్ట్ డిపెండెన్సీలను జోడించడంతో ప్రారంభిద్దాం - మోచా & చాయ్: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# లేదా మీరు npm వాడుతుంటే -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -ఇప్పుడు `Waffle` మరియు `ethers` ని జోడిద్దాం: - -```bash -yarn add --dev ethereum-waffle ethers -# లేదా మీరు npm వాడుతుంటే -npm install ethereum-waffle ethers --save-dev -``` - -మీ ప్రాజెక్ట్ నిర్మాణం ఇప్పుడు ఇలా ఉండాలి: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. స్మార్ట్ కాంట్రాక్ట్** {#2-smart-contract} - -డైనమిక్ మాకింగ్ ప్రారంభించడానికి, మనకు డిపెండెన్సీలతో కూడిన స్మార్ట్ కాంట్రాక్ట్ అవసరం. చింతించకండి, నేను మీకు సహాయం చేస్తాను! - -ఇక్కడ `Solidity`లో వ్రాసిన ఒక సాధారణ స్మార్ట్ కాంట్రాక్ట్ ఉంది, దీని ఏకైక ఉద్దేశ్యం మనం ధనవంతులమా కాదా అని తనిఖీ చేయడం. మన దగ్గర తగినన్ని టోకెన్లు ఉన్నాయో లేదో తనిఖీ చేయడానికి ఇది ERC20 టోకెన్‌ను ఉపయోగిస్తుంది. దీన్ని `./contracts/AmIRichAlready.sol`లో ఉంచండి. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -మేము డైనమిక్ మాకింగ్ ఉపయోగించాలనుకుంటున్నాము కాబట్టి మాకు పూర్తి ERC20 అవసరం లేదు, అందుకే మేము కేవలం ఒక ఫంక్షన్‌తో IERC20 ఇంటర్‌ఫేస్‌ను ఉపయోగిస్తున్నాము. - -ఈ కాంట్రాక్ట్‌ను రూపొందించడానికి సమయం ఆసన్నమైంది! దాని కోసం మేము `Waffle`ని ఉపయోగిస్తాము. మొదట, మేము కంపైలేషన్ ఎంపికలను పేర్కొనే ఒక సాధారణ `waffle.json` కాన్ఫిగ్ ఫైల్‌ను సృష్టించబోతున్నాము. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -ఇప్పుడు మనం వాఫిల్‌తో కాంట్రాక్ట్‌ను నిర్మించడానికి సిద్ధంగా ఉన్నాము: - -```bash -npx waffle -``` - -సులభం, కదా? `build/` ఫోల్డర్‌లో కాంట్రాక్ట్ మరియు ఇంటర్‌ఫేస్‌కు సంబంధించిన రెండు ఫైల్‌లు కనిపించాయి. పరీక్ష కోసం మేము వాటిని తర్వాత ఉపయోగిస్తాము. - -### **3. పరీక్షించడం** {#3-testing} - -వాస్తవ పరీక్ష కోసం `AmIRichAlready.test.ts` అనే ఫైల్‌ను సృష్టిద్దాం. అన్నింటికంటే ముందు, మనం దిగుమతులను నిర్వహించాలి. తర్వాత మనకు అవి అవసరం: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -JS డిపెండెన్సీలు మినహా, మనము నిర్మించిన కాంట్రాక్ట్ మరియు ఇంటర్‌ఫేస్‌ను దిగుమతి చేసుకోవాలి: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -పరీక్షించడానికి `Waffle` `chai`ని ఉపయోగిస్తుంది. అయితే, మనం దానిని ఉపయోగించే ముందు, `Waffle` యొక్క మ్యాచ్‌లను `chai`లోకే ఇంజెక్ట్ చేయాలి: - -```typescript -use(solidity) -``` - -ప్రతి పరీక్షకు ముందు కాంట్రాక్ట్ స్థితిని రీసెట్ చేసే `beforeEach()` ఫంక్షన్‌ను మనం అమలు చేయాలి. అక్కడ మనకేం కావాలో ముందు ఆలోచిద్దాం. ఒక కాంట్రాక్ట్‌ను అమలు చేయడానికి మాకు రెండు విషయాలు కావాలి: ఒక వాలెట్ మరియు `AmIRichAlready` కాంట్రాక్ట్ కోసం ఒక ఆర్గ్యుమెంట్‌గా పాస్ చేయడానికి ఒక అమలు చేయబడిన ERC20 కాంట్రాక్ట్. - -ముందుగా మనం ఒక వాలెట్‌ను సృష్టిస్తాము: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -అప్పుడు మనం ఒక ERC20 కాంట్రాక్ట్‌ను అమలు చేయాలి. ఇక్కడే క్లిష్టమైన భాగం ఉంది - మన దగ్గర ఒక ఇంటర్‌ఫేస్ మాత్రమే ఉంది. ఇక్కడే `Waffle` మనల్ని రక్షించడానికి వస్తుంది. `Waffle`లో ఒక మ్యాజికల్ `deployMockContract()` ఫంక్షన్ ఉంది, ఇది ఇంటర్‌ఫేస్ యొక్క _abi_ని మాత్రమే ఉపయోగించి కాంట్రాక్ట్‌ను సృష్టిస్తుంది: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -ఇప్పుడు వాలెట్ మరియు అమలు చేయబడిన ERC20 రెండింటితో, మనం ముందుకు వెళ్లి `AmIRichAlready` కాంట్రాక్ట్‌ను అమలు చేయవచ్చు: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -వీటన్నింటితో, మా `beforeEach()` ఫంక్షన్ పూర్తయింది. ఇప్పటివరకు మీ `AmIRichAlready.test.ts` ఫైల్ ఇలా ఉండాలి: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -`AmIRichAlready` కాంట్రాక్ట్ కోసం మొదటి టెస్ట్ వ్రాద్దాం. మన టెస్ట్ దేని గురించి ఉండాలని మీరు అనుకుంటున్నారు? అవును, మీరు చెప్పింది నిజమే! మనం ఇప్పటికే ధనవంతులమా కాదా అని తనిఖీ చేయాలి :) - -కానీ ఒక్క నిమిషం ఆగండి. మన మాక్డ్ కాంట్రాక్ట్‌కు ఏ విలువలు తిరిగి ఇవ్వాలో ఎలా తెలుస్తుంది? `balanceOf()` ఫంక్షన్ కోసం మేము ఏ లాజిక్‌ను అమలు చేయలేదు. మళ్ళీ, వాఫిల్ ఇక్కడ సహాయపడుతుంది. మా మాక్డ్ కాంట్రాక్ట్‌లో ఇప్పుడు కొన్ని కొత్త ఫ్యాన్సీ విషయాలు ఉన్నాయి: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -ఈ జ్ఞానంతో మనం చివరకు మన మొదటి పరీక్షను వ్రాయగలము: - -```typescript -it("వాలెట్‌లో 1000000 టోకెన్‌ల కంటే తక్కువ ఉంటే ఫాల్స్‌ని అందిస్తుంది", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -ఈ పరీక్షను భాగాలుగా విభజిద్దాం: - -1. మేము మా మాక్ ERC20 కాంట్రాక్ట్‌ను ఎల్లప్పుడూ 999999 టోకెన్‌ల బ్యాలెన్స్‌ను తిరిగి ఇచ్చేలా సెట్ చేసాము. -2. `contract.check()` పద్ధతి `false`ని తిరిగి ఇస్తుందో లేదో తనిఖీ చేయండి. - -మేము దీన్ని ప్రారంభించడానికి సిద్ధంగా ఉన్నాము: - -![ఒక పరీక్ష పాస్ అవుతోంది](./test-one.png) - -కాబట్టి పరీక్ష పనిచేస్తుంది, కానీ... ఇంకా మెరుగుపరచడానికి కొంత ఆస్కారం ఉంది. `balanceOf()` ఫంక్షన్ ఎల్లప్పుడూ 999999ని తిరిగి ఇస్తుంది. ఫంక్షన్ ఏదైనా తిరిగి ఇవ్వాల్సిన వాలెట్‌ను పేర్కొనడం ద్వారా మనం దానిని మెరుగుపరచవచ్చు - నిజమైన కాంట్రాక్ట్ లాగానే: - -```typescript -it("వాలెట్‌లో 1000001 టోకెన్‌ల కంటే తక్కువ ఉంటే ఫాల్స్‌ని అందిస్తుంది", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -ఇప్పటివరకు, మనం తగినంత ధనవంతులు కానప్పుడు మాత్రమే పరీక్షించాము. దానికి బదులుగా వ్యతిరేకతను పరీక్షిద్దాం: - -```typescript -it("వాలెట్‌లో కనీసం 1000001 టోకెన్లు ఉంటే ట్రూని అందిస్తుంది", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -మీరు పరీక్షలను నడుపుతారు... - -![రెండు పరీక్షలు పాస్ అవుతున్నాయి](test-two.png) - -...మరియు ఇక్కడ మీరు ఉన్నారు! మా కాంట్రాక్ట్ ఉద్దేశించిన విధంగా పనిచేస్తున్నట్లు అనిపిస్తుంది :) - -## కాంట్రాక్ట్ కాల్స్‌ను పరీక్షించడం {#testing-contract-calls} - -ఇప్పటివరకు ఏమి చేసామో సంగ్రహిద్దాం. మేము మా `AmIRichAlready` కాంట్రాక్ట్ యొక్క కార్యాచరణను పరీక్షించాము మరియు ఇది సరిగ్గా పనిచేస్తున్నట్లు అనిపిస్తుంది. అంటే మనం పూర్తి చేసాము, కదా? ఖచ్చితంగా కాదు! వాఫిల్ మన కాంట్రాక్ట్‌ను మరింత పరీక్షించడానికి అనుమతిస్తుంది. కానీ సరిగ్గా ఎలా? సరే, వాఫిల్ యొక్క ఆయుధశాలలో `calledOnContract()` మరియు `calledOnContractWith()` మ్యాచ్‌చర్‌లు ఉన్నాయి. మా కాంట్రాక్ట్ ERC20 మాక్ కాంట్రాక్ట్‌ను పిలిచిందో లేదో తనిఖీ చేయడానికి అవి మమ్మల్ని అనుమతిస్తాయి. ఈ మ్యాచ్‌చర్‌లలో ఒకదానితో ఇక్కడ ఒక ప్రాథమిక పరీక్ష ఉంది: - -```typescript -it("ERC20 టోకెన్‌పై కాంట్రాక్ట్ బ్యాలెన్స్‌ఆఫ్‌ను పిలిచిందో లేదో తనిఖీ చేస్తుంది", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -మనం ఇంకా ముందుకు వెళ్లి, నేను మీకు చెప్పిన ఇతర మ్యాచ్‌చర్‌తో ఈ పరీక్షను మెరుగుపరచవచ్చు: - -```typescript -it("ERC20 టోకెన్‌పై నిర్దిష్ట వాలెట్‌తో కాంట్రాక్ట్ బ్యాలెన్స్‌ఆఫ్‌ను పిలిచిందో లేదో తనిఖీ చేస్తుంది", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -పరీక్షలు సరైనవో కాదో తనిఖీ చేద్దాం: - -![మూడు పరీక్షలు పాస్ అవుతున్నాయి](test-three.png) - -గొప్పది, అన్ని పరీక్షలు ఆకుపచ్చగా ఉన్నాయి. - -వాఫిల్‌తో కాంట్రాక్ట్ కాల్స్‌ను పరీక్షించడం చాలా సులభం. మరియు ఇక్కడ ఉత్తమ భాగం ఉంది. ఈ మ్యాచ్‌చర్‌లు సాధారణ మరియు మాక్డ్ కాంట్రాక్టులు రెండింటితోనూ పనిచేస్తాయి! ఇతర సాంకేతికతల కోసం ప్రసిద్ధ టెస్టింగ్ లైబ్రరీల విషయంలో లాగా, కోడ్‌ను ఇంజెక్ట్ చేయడం కంటే వాఫిల్ EVM కాల్స్‌ను రికార్డ్ చేసి ఫిల్టర్ చేయడం దీనికి కారణం. - -## ముగింపు రేఖ {#the-finish-line} - -అభినందనలు! ఇప్పుడు కాంట్రాక్ట్ కాల్స్‌ను పరీక్షించడానికి మరియు కాంట్రాక్టులను డైనమిక్‌గా మాక్ చేయడానికి వాఫిల్‌ను ఎలా ఉపయోగించాలో మీకు తెలుసు. కనుగొనడానికి ఇంకా చాలా ఆసక్తికరమైన ఫీచర్లు ఉన్నాయి. నేను వాఫిల్ డాక్యుమెంటేషన్‌లోకి ప్రవేశించమని సిఫార్సు చేస్తున్నాను. - -వాఫిల్ డాక్యుమెంటేషన్ [ఇక్కడ](https://ethereum-waffle.readthedocs.io/) అందుబాటులో ఉంది. - -ఈ ట్యుటోరియల్ కోసం సోర్స్ కోడ్‌ను [ఇక్కడ](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls) కనుగొనవచ్చు. - -మీరు ఆసక్తి చూపే ట్యుటోరియల్స్: - -- [వాఫిల్‌తో స్మార్ట్ కాంట్రాక్టులను పరీక్షించడం](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/te/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/te/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 57baa869cf0..00000000000 --- a/public/content/translations/te/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "హార్డ్‌హ్యాట్ మరియు ఇథర్స్‌తో వాఫిల్ హలో వరల్డ్ ట్యుటోరియల్" -description: "హార్డ్‌హ్యాట్ మరియు ఇథర్స్.js తో మీ మొదటి వాఫిల్ ప్రాజెక్ట్ ను తయారు చేయండి" -author: "MiZiet" -tags: - [ - "waffle", - "స్మార్ట్ కాంట్రాక్టులు", - "దృఢత్వం", - "పరీక్షించడం", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: te -published: 2020-10-16 ---- - -ఈ [వాఫిల్](https://ethereum-waffle.readthedocs.io) ట్యుటోరియల్‌లో, మనం [హార్డ్‌హ్యాట్](https://hardhat.org/) మరియు [ethers.js](https://docs.ethers.io/v5/) ఉపయోగించి ఒక సాధారణ "హలో వరల్డ్" స్మార్ట్ కాంట్రాక్ట్ ప్రాజెక్ట్‌ను ఎలా సెటప్ చేయాలో నేర్చుకుంటాం. ఆ తర్వాత మన స్మార్ట్ కాంట్రాక్ట్‌కు కొత్త కార్యాచరణను ఎలా జోడించాలో మరియు దానిని వాఫిల్‌తో ఎలా పరీక్షించాలో మనం నేర్చుకుంటాం. - -కొత్త ప్రాజెక్ట్‌ను సృష్టించడం ద్వారా ప్రారంభిద్దాం: - -```bash -yarn init -``` - -లేదా - -```bash -npm init -``` - -మరియు అవసరమైన ప్యాకేజీలను ఇన్‌స్టాల్ చేయడం: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -లేదా - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -`npx hardhat` రన్ చేయడం ద్వారా ఒక నమూనా హార్డ్‌హ్యాట్ ప్రాజెక్ట్‌ను సృష్టించడం తదుపరి దశ. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 హార్డ్‌హ్యాట్ v2.0.3కి స్వాగతం 👷‍ - -? మీరు ఏమి చేయాలనుకుంటున్నారు? … -❯ ఒక నమూనా ప్రాజెక్ట్‌ను సృష్టించండి -ఖాళీ hardhat.config.jsని సృష్టించండి -నిష్క్రమించండి -``` - -`Create a sample project`ని ఎంచుకోండి - -మన ప్రాజెక్ట్ నిర్మాణం ఈ విధంగా ఉండాలి: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### ఇప్పుడు ఈ ఫైల్‌లలో కొన్నింటి గురించి మాట్లాడుకుందాం: {#now-lets-talk} - -- Greeter.sol - సాలిడిటీలో వ్రాసిన మన స్మార్ట్ కాంట్రాక్ట్; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("గ్రీటింగ్‌తో గ్రీటర్‌ను డిప్లాయ్ చేస్తోంది:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("గ్రీటింగ్‌ను '%s' నుండి '%s'కి మారుస్తోంది", greeting, _greeting); -greeting = _greeting; -} -} -``` - -మన స్మార్ట్ కాంట్రాక్ట్‌ను మూడు భాగాలుగా విభజించవచ్చు: - -1. కన్స్ట్రక్టర్ - ఇక్కడ మనం `greeting` అనే స్ట్రింగ్ రకం వేరియబుల్‌ను ప్రకటిస్తాము, -2. ఫంక్షన్ గ్రీట్ - పిలిచినప్పుడు `greeting`ను తిరిగి ఇచ్చే ఫంక్షన్, -3. ఫంక్షన్ సెట్‌గ్రీటింగ్ - `greeting` విలువను మార్చడానికి మనకు అనుమతించే ఫంక్షన్. - -- sample-test.js - మన పరీక్షల ఫైల్ - -```js -describe("గ్రీటర్", function () { - it("ఒకసారి మార్చిన తర్వాత కొత్త గ్రీటింగ్‌ను తిరిగి ఇవ్వాలి", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("హలో, వరల్డ్!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("హలో, వరల్డ్!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### తదుపరి దశలో మన కాంట్రాక్ట్‌ను కంపైల్ చేయడం మరియు పరీక్షలను అమలు చేయడం ఉంటాయి: {#compiling-and-testing} - -వాఫిల్ పరీక్షలు మోచా (ఒక టెస్ట్ ఫ్రేమ్‌వర్క్)ను చాయ్ (ఒక అస్సర్షన్ లైబ్రరీ)తో కలిపి ఉపయోగిస్తాయి. మీరు చేయాల్సిందల్లా `npx hardhat test`ను అమలు చేసి, కింది సందేశం కనిపించే వరకు వేచి ఉండటమే. - -```bash -✓ ఒకసారి మార్చిన తర్వాత కొత్త గ్రీటింగ్‌ను తిరిగి ఇవ్వాలి -``` - -### ఇప్పటివరకు అంతా బాగానే ఉంది, మన ప్రాజెక్ట్‌కు మరికొంత సంక్లిష్టతను జోడిద్దాం {#adding-complexity} - -ఎవరైనా గ్రీటింగ్‌గా ఖాళీ స్ట్రింగ్‌ను జోడించే పరిస్థితిని ఊహించుకోండి. అది ఆత్మీయమైన పలకరింపు కాదు, కదా? -అలా జరగకుండా చూసుకుందాం: - -ఎవరైనా ఖాళీ స్ట్రింగ్‌ను పంపినప్పుడు సాలిడిటీ యొక్క `revert`ని ఉపయోగించాలనుకుంటున్నాము. మంచి విషయం ఏమిటంటే, వాఫిల్ యొక్క చాయ్ మ్యాచర్ `to.be.revertedWith()`తో మనం ఈ కార్యాచరణను సులభంగా పరీక్షించవచ్చు. - -```js -it("ఖాళీ స్ట్రింగ్‌ను పంపినప్పుడు తిరిగి పంపాలి", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("హలో, వరల్డ్!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "గ్రీటింగ్ ఖాళీగా ఉండకూడదు" - ) -}) -``` - -మన కొత్త పరీక్ష పాస్ కాలేదని తెలుస్తోంది: - -```bash -గ్రీటింగ్‌తో గ్రీటర్‌ను డిప్లాయ్ చేస్తోంది: హలో, వరల్డ్! -'హలో, వరల్డ్!' నుండి 'Hola, mundo!'కి గ్రీటింగ్‌ను మారుస్తోంది - ✓ ఒకసారి మార్చిన తర్వాత కొత్త గ్రీటింగ్‌ను తిరిగి ఇవ్వాలి (1514ms) -గ్రీటింగ్‌తో గ్రీటర్‌ను డిప్లాయ్ చేస్తోంది: హలో, వరల్డ్! -'హలో, వరల్డ్!' నుండి ''కి గ్రీటింగ్‌ను మారుస్తోంది - 1) ఖాళీ స్ట్రింగ్‌ను పంపినప్పుడు తిరిగి పంపాలి - - - 1 ఉత్తీర్ణం (2s) - 1 విఫలం -``` - -ఈ కార్యాచరణను మన స్మార్ట్ కాంట్రాక్ట్‌లో అమలు చేద్దాం: - -```solidity -require(bytes(_greeting).length > 0, "గ్రీటింగ్ ఖాళీగా ఉండకూడదు"); -``` - -ఇప్పుడు, మన సెట్ గ్రీటింగ్ ఫంక్షన్ ఈ విధంగా కనిపిస్తుంది: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "గ్రీటింగ్ ఖాళీగా ఉండకూడదు"); -console.log("గ్రీటింగ్‌ను '%s' నుండి '%s'కి మారుస్తోంది", greeting, _greeting); -greeting = _greeting; -} -``` - -పరీక్షలను మళ్ళీ అమలు చేద్దాం: - -```bash -✓ ఒకసారి మార్చిన తర్వాత కొత్త గ్రీటింగ్‌ను తిరిగి ఇవ్వాలి (1467ms) -✓ ఖాళీ స్ట్రింగ్‌ను పంపినప్పుడు తిరిగి పంపాలి (276ms) - -2 ఉత్తీర్ణం (2s) -``` - -అభినందనలు! మీరు సాధించారు :) - -### ముగింపు {#conclusion} - -మేము వాఫిల్, హార్డ్‌హ్యాట్ మరియు ఇథర్స్.jsలతో ఒక సాధారణ ప్రాజెక్ట్‌ను రూపొందించాము. ప్రాజెక్ట్‌ను ఎలా సెటప్ చేయాలో, పరీక్షను జోడించడం మరియు కొత్త కార్యాచరణను ఎలా అమలు చేయాలో మనం నేర్చుకున్నాము. - -మీ స్మార్ట్ కాంట్రాక్ట్‌లను పరీక్షించడానికి మరిన్ని గొప్ప చాయ్ మ్యాచర్‌ల కోసం, [అధికారిక వాఫిల్ డాక్స్](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)ను చూడండి. diff --git a/public/content/translations/te/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/te/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 97e4aaef8b7..00000000000 --- a/public/content/translations/te/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: "Waffle లైబ్రరీతో సులభమైన స్మార్ట్ కాంట్రాక్టును పరీక్షిస్తోంది" -description: "ప్రారంభకులకు ట్యుటోరియల్" -author: Ewa Kowalska -tags: - [ - "స్మార్ట్ కాంట్రాక్టులు", - "దృఢత్వం", - "Waffle", - "పరీక్షించడం" - ] -skill: beginner -lang: te -published: 2021-02-26 ---- - -## ఈ ట్యుటోరియల్‌లో మీరు ఎలా చేయాలో నేర్చుకుంటారు {#in-this-tutorial-youll-learn-how-to} - -- వాలెట్ బ్యాలెన్స్ మార్పులను పరీక్షించండి -- పేర్కొన్న ఆర్గ్యుమెంట్‌లతో ఈవెంట్‌ల ఉద్గారాలను పరీక్షించండి -- ఒక లావాదేవీని తిరిగి పంపినట్లు నిర్ధారించండి - -## అనుమానాలు {#assumptions} - -- మీరు కొత్త జావాస్క్రిప్ట్ లేదా టైప్‌స్క్రిప్ట్ ప్రాజెక్ట్‌ను సృష్టించవచ్చు -- జావాస్క్రిప్ట్‌లో పరీక్షలతో మీకు కొంత ప్రాథమిక అనుభవం ఉంది -- మీరు యార్న్ లేదా ఎన్‌పిఎమ్ వంటి కొన్ని ప్యాకేజీ మేనేజర్‌లను ఉపయోగించారు -- మీకు స్మార్ట్ కాంట్రాక్టులు మరియు సాలిడిటీ గురించి చాలా ప్రాథమిక పరిజ్ఞానం ఉంది - -## ప్రారంభించడం {#getting-started} - -ట్యుటోరియల్ యార్న్‌ను ఉపయోగించి టెస్ట్ సెటప్ మరియు రన్‌ను ప్రదర్శిస్తుంది, కానీ మీరు ఎన్‌పిఎమ్‌ను ఇష్టపడితే ఎటువంటి సమస్య లేదు - నేను అధికారిక Waffle [డాక్యుమెంటేషన్](https://ethereum-waffle.readthedocs.io/en/latest/index.html) కు సరైన రిఫరెన్స్‌లను అందిస్తాను. - -## డిపెండెన్సీలను ఇన్‌స్టాల్ చేయండి {#install-dependencies} - -మీ ప్రాజెక్ట్ యొక్క డెవ్ డిపెండెన్సీలకు [జోడించు](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) ethereum-waffle మరియు టైప్‌స్క్రిప్ట్ డిపెండెన్సీలను. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## ఉదాహరణ స్మార్ట్ కాంట్రాక్ట్ {#example-smart-contract} - -ట్యుటోరియల్ సమయంలో మేము ఒక సాధారణ స్మార్ట్ కాంట్రాక్ట్ ఉదాహరణ - EtherSplitter పై పని చేస్తాము. ఎవరినైనా కొంత wei పంపడానికి మరియు ఇద్దరు ముందుగా నిర్వచించిన రిసీవర్ల మధ్య సమానంగా విభజించడానికి అనుమతించడం తప్ప ఇది పెద్దగా ఏమీ చేయదు. -స్ప్లిట్ ఫంక్షన్‌కు wei సంఖ్య సరిగా ఉండాలి, లేకపోతే అది తిరిగి వస్తుంది. ఇద్దరు రిసీవర్ల కోసం ఇది wei బదిలీని నిర్వహిస్తుంది, దాని తరువాత బదిలీ ఈవెంట్ యొక్క ఉద్గారం ఉంటుంది. - -`src/EtherSplitter.sol` లో EtherSplitter కోడ్ యొక్క స్నిప్పెట్‌ను ఉంచండి. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'సరిగా లేని wei మొత్తం అనుమతించబడదు'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## కాంట్రాక్ట్‌ను కంపైల్ చేయండి {#compile-the-contract} - -కాంట్రాక్ట్‌ను [కంపైల్ చేయడానికి](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) package.json ఫైల్‌కు కింది ఎంట్రీని జోడించండి: - -```json -"scripts": { - "build": "waffle" - } -``` - -తరువాత, ప్రాజెక్ట్ రూట్ డైరెక్టరీలో Waffle కాన్ఫిగరేషన్ ఫైల్‌ను సృష్టించండి - `waffle.json` - ఆపై కింది కాన్ఫిగరేషన్‌ను అక్కడ అతికించండి: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -`yarn build` ను అమలు చేయండి. ఫలితంగా, `build` డైరెక్టరీ JSON ఫార్మాట్‌లో EtherSplitter కంపైల్ చేయబడిన కాంట్రాక్ట్‌తో కనిపిస్తుంది. - -## టెస్ట్ సెటప్ {#test-setup} - -Waffle తో పరీక్షించడానికి చాయ్ మ్యాచర్‌లు మరియు మోచాను ఉపయోగించడం అవసరం, కాబట్టి మీరు వాటిని మీ ప్రాజెక్ట్‌కు [జోడించాలి](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests). మీ package.json ఫైల్‌ను అప్‌డేట్ చేయండి మరియు స్క్రిప్ట్స్ భాగంలో `test` ఎంట్రీని జోడించండి: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -మీరు మీ పరీక్షలను [అమలు చేయాలనుకుంటే](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests), కేవలం `yarn test` ను అమలు చేయండి. - -## పరీక్షించడం {#testing} - -ఇప్పుడు `test` డైరెక్టరీని సృష్టించండి మరియు కొత్త ఫైల్ `test\EtherSplitter.test.ts` ను సృష్టించండి. -కింది స్నిప్పెట్‌ను కాపీ చేసి, దాన్ని మా టెస్ట్ ఫైల్‌లో అతికించండి. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("ఈథర్ స్ప్లిట్టర్", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // ఇక్కడ పరీక్షలను జోడించండి -}) -``` - -మేము ప్రారంభించడానికి ముందు కొన్ని మాటలు. -`MockProvider` బ్లాక్‌చెయిన్ యొక్క మాక్ వెర్షన్‌తో వస్తుంది. ఇది EtherSplitter కాంట్రాక్ట్‌ను పరీక్షించడానికి మాకు ఉపయోగపడే మాక్ వాలెట్లను కూడా అందిస్తుంది. ప్రొవైడర్‌పై `getWallets()` పద్ధతిని కాల్ చేయడం ద్వారా మనం పది వాలెట్లను పొందవచ్చు. ఉదాహరణలో, మేము మూడు వాలెట్లను పొందుతాము - పంపినవారికి మరియు ఇద్దరు రిసీవర్ల కోసం. - -తరువాత, మేము 'స్ప్లిట్టర్' అనే వేరియబుల్‌ను ప్రకటిస్తాము - ఇది మా మాక్ EtherSplitter కాంట్రాక్ట్. `deployContract` పద్ధతి ద్వారా ప్రతి ఒక్క పరీక్ష అమలుకు ముందు ఇది సృష్టించబడుతుంది. ఈ పద్ధతి మొదటి పరామీటర్‌గా పంపబడిన వాలెట్ నుండి (మా విషయంలో పంపినవారి వాలెట్) ఒక కాంట్రాక్ట్ యొక్క విస్తరణను అనుకరిస్తుంది. రెండవ పరామీటర్ పరీక్షించబడిన కాంట్రాక్ట్ యొక్క ABI మరియు బైట్‌కోడ్ - మేము `build` డైరెక్టరీ నుండి కంపైల్ చేయబడిన EtherSplitter కాంట్రాక్ట్ యొక్క json ఫైల్‌ను అక్కడ పంపుతాము. మూడవ పరామీటర్ కాంట్రాక్ట్ యొక్క కన్‌స్ట్రక్టర్ ఆర్గ్యుమెంట్‌లతో కూడిన ఒక శ్రేణి, ఇది మా విషయంలో, రిసీవర్ల యొక్క రెండు చిరునామాలు. - -## బ్యాలెన్స్‌లను మార్చండి {#changebalances} - -మొదట, స్ప్లిట్ పద్ధతి వాస్తవానికి రిసీవర్ల వాలెట్ల బ్యాలెన్స్‌లను మారుస్తుందో లేదో తనిఖీ చేస్తాము. మేము పంపినవారి ఖాతా నుండి 50 wei విభజిస్తే, ఇద్దరు రిసీవర్ల బ్యాలెన్స్‌లు 25 wei పెరగాలని మేము ఆశిస్తాము. మేము Waffle యొక్క `changeBalances` మ్యాచర్‌ను ఉపయోగిస్తాము: - -```ts -it("ఖాతాల బ్యాలెన్స్‌లను మారుస్తుంది", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -మ్యాచర్ యొక్క మొదటి పరామీటర్‌గా, మేము రిసీవర్ల వాలెట్ల శ్రేణిని పంపుతాము, మరియు రెండవదిగా - సంబంధిత ఖాతాలపై ఆశించిన పెరుగుదలల శ్రేణి. -ఒక నిర్దిష్ట వాలెట్ యొక్క బ్యాలెన్స్‌ను తనిఖీ చేయాలనుకుంటే, మేము `changeBalance` మ్యాచర్‌ను కూడా ఉపయోగించవచ్చు, దీనికి క్రింది ఉదాహరణలో వలె శ్రేణులను పంపడం అవసరం లేదు: - -```ts -it("ఖాతా బ్యాలెన్స్‌ను మారుస్తుంది", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -`changeBalance` మరియు `changeBalances` రెండింటి సందర్భాల్లోనూ మేము స్ప్లిట్ ఫంక్షన్‌ను కాల్‌బ్యాక్‌గా పంపుతామని గమనించండి, ఎందుకంటే మ్యాచర్‌కు కాల్‌కు ముందు మరియు తరువాత బ్యాలెన్స్‌ల స్థితిని యాక్సెస్ చేయాలి. - -తరువాత, ప్రతి wei బదిలీ తర్వాత బదిలీ ఈవెంట్ జారీ చేయబడిందా అని మేము పరీక్షిస్తాము. మేము Waffle నుండి మరొక మ్యాచర్‌కు వెళ్తాము: - -## జారీ చేయి {#emit} - -```ts -it("మొదటి రిసీవర్‌కు బదిలీపై ఈవెంట్‌ను జారీ చేస్తుంది", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("రెండవ రిసీవర్‌కు బదిలీపై ఈవెంట్‌ను జారీ చేస్తుంది", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit` మ్యాచర్ ఒక పద్ధతిని కాల్ చేసినప్పుడు కాంట్రాక్ట్ ఒక ఈవెంట్‌ను జారీ చేసిందో లేదో తనిఖీ చేయడానికి మాకు అనుమతిస్తుంది. `emit` మ్యాచర్‌కు పరామీటర్లుగా, ఈవెంట్‌ను జారీ చేస్తుందని మేము ఊహించిన మాక్ కాంట్రాక్ట్‌ను, ఆ ఈవెంట్ పేరుతో పాటు అందిస్తాము. మా విషయంలో, మాక్ కాంట్రాక్ట్ `స్ప్లిట్టర్` మరియు ఈవెంట్ పేరు - `Transfer`. ఈవెంట్ జారీ చేయబడిన ఆర్గ్యుమెంట్‌ల యొక్క ఖచ్చితమైన విలువలను కూడా మేము ధృవీకరించవచ్చు - మా ఈవెంట్ డిక్లరేషన్ ఆశించినన్ని ఆర్గ్యుమెంట్‌లను `withArgs` మ్యాచర్‌కు పంపుతాము. EtherSplitter కాంట్రాక్ట్ విషయంలో, మేము పంపినవారు మరియు రిసీవర్ యొక్క చిరునామాలను బదిలీ చేయబడిన wei మొత్తంతో పాటు పంపుతాము. - -## తో వెనక్కు తిరిగింది {#revertedwith} - -చివరి ఉదాహరణగా, సరిగా లేని wei సంఖ్య విషయంలో లావాదేవీ వెనక్కి తిరిగిందో లేదో తనిఖీ చేస్తాము. మేము `revertedWith` మ్యాచర్‌ను ఉపయోగిస్తాము: - -```ts -it("Vei మొత్తం సరిగా లేనప్పుడు తిరిగి వస్తుంది", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "సరిగా లేని wei మొత్తం అనుమతించబడదు" - ) -}) -``` - -పరీక్ష, ఉత్తీర్ణత సాధిస్తే, లావాదేవీ వాస్తవంగా వెనక్కి తిరిగిందని మాకు హామీ ఇస్తుంది. అయితే, మేము `require` స్టేట్‌మెంట్‌లో పంపిన సందేశాలు మరియు `revertedWith` లో మనం ఆశించే సందేశం మధ్య ఖచ్చితమైన సరిపోలిక కూడా ఉండాలి. మేము EtherSplitter కాంట్రాక్ట్ కోడ్‌కు తిరిగి వెళితే, wei మొత్తం కోసం `require` స్టేట్‌మెంట్‌లో, మేము ఈ సందేశాన్ని అందిస్తాము: 'సరిగా లేని wei మొత్తం అనుమతించబడదు'. ఇది మా పరీక్షలో మేము ఆశించే సందేశంతో సరిపోలుతుంది. అవి సమానంగా లేకపోతే, పరీక్ష విఫలమవుతుంది. - -## అభినందనలు! {#congratulations} - -మీరు Waffleతో స్మార్ట్ కాంట్రాక్టులను పరీక్షించడం వైపు మీ మొదటి పెద్ద అడుగు వేశారు! diff --git a/public/content/translations/tr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/tr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index cdceb252577..00000000000 --- a/public/content/translations/tr/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: "ERC-20 token'larını Waffle ile test etme" -description: "Solidity akıllı sözleşmelerini nasıl test edeceğinizi ve Waffle ile akıllı sözleşme eşleyicileri nasıl kullanacağınızı öğrenin." -author: Vladislav Starostenko -tags: - - "waffle" - - "akıllı sözleşmeler" - - "solidity" - - "test" - - "erc-20" -skill: intermediate -lang: tr -published: 2020-10-16 ---- - -Bu öğreticide şunları nasıl yapacağınızı öğreneceksiniz: - -- Waffle ile akıllı sözleşmeler için testler yazma -- Waffle ile akıllı sözleşmeleri test etmek için bazı popüler eşleyicileri kullanma - -Varsayımlar: - -- bir terminalde gezinebildiğiniz, -- yeni bir `JavaScript` projesi oluşturabildiğiniz, -- `JavaScript`'te birkaç satır yazdınız, -- `JavaScript`'te birkaç test yazdınız, -- JavaScripts'in paket yükleyicisi olan `yarn` veya `npm` kullandığınız. - -Buna karşın, eğer varsayımlardan herhangi biri doğru değilse veya bu makaledeki kodu yeniden uygulamayı düşünmüyorsanız, büyük ihtimalle yine de gayet iyi şekilde takip edebilirsiniz. - -## Waffle hakkında kısa bilgiler {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io), akıllı sözleşmeler yazmak ve test etmek için en gelişmiş kütüphanedir. - -[JavaScript API](/developers/docs/apis/javascript/), ethers-js ile çalışır. - -Daha fazla ayrıntıyı [Waffle belgelerinde](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation) okuyabilirsiniz! - -## Hızlı öğretici {#the-quick-tutorial} - -Her şeyden önce, yeni bir `JavaScript` veya `TypeScript` projesi oluşturun (Ben `TS` kullanacağım, ancak `JS` kullanıyorsanız problem değil): - -Şöyle bir şey: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## 1. Adım: Projenize waffle kurun [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -Başlamak için, `ethereum-waffle` kurun. Bu öğreticide ben `yarn` kullanacağım, yani `ethereum-waffle` kurmak için şunu çalıştırın: - -```bash - yarn add --dev ethereum-waffle -``` - -## 2. Adım: Bir akıllı sözleşme yazın [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -Bu öğreticide, [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) OpenZeppelin token'ını kullanacağım[](https://openzeppelin.com). - -Yani, `yarn` ile kurarak `OpenZeppelin` ekleyin: - -```bash - yarn add @openzeppelin/contracts -D -``` - -Sonrasında `BasicToken.sol` sözleşmesini `src` klasöründe oluşturun: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## 3. Adım: Akıllı sözleşmenizi derleyin [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -Akıllı sözleşmenizi derlemek için projenizin `package.json` dosyasına aşağıdaki girişi ekleyin: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -Ayrıca projenizin ana dizinine `waffle.json` dosyasını ekleyin. - -Bir `waffle.json` yapılandırma örneği: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Waffle yapılandırması hakkında daha fazla ayrıntıyı [buradan](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration) okuyabilirsiniz. - -Sonrasında akıllı sözleşmenizi derlemek için sadece `yarn build` çalıştırın. - -Waffle'ın sözleşmenizi derlediğini ve ortaya çıkan JSON çıktısını `build` dizinine yerleştirdiğini görmelisiniz. - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## 4. Adım: Akıllı sözleşmenizi test edin [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### 4.1. Adım: Gerekli bağımlılıkları ekleyin [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -Bir Akıllı Sözleşmeyi başarıyla yazdıktan sonra onu test edebiliriz. Bunu yapmak için `Waffle` kullanacağız. - -`Waffle` testleri `Mocha` ve onun yanında `Chai` kullanılarak yazılmıştır. Farklı bir test ortamı kullanabiliriz, ancak `Waffle` eşleyicileri yalnızca `Chai` ile çalışır. - -Yani, bağımlılıklarımıza `Chai` eklemeliyiz: - -```bash - yarn add --dev mocha chai -``` - -### 4.2. Adım: Test dosyası oluşturun [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -Testimizi yazmak için test dizinimizde `BasicToken.test.ts` dosyası oluşturmamız gerekiyor. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -Yani, token'ımızı dağıtmak için `Waffle`'dan `deployContract` yöntemini kullanıyoruz. Argüman olarak, sözleşmemizin ve varsayılan bakiyemizin derlenmiş json dosyası olan `wallet`'ı geçmeliyiz. - -`Waffle` ayrıca, bir sözleşmeyi dağıtmayı çok kolaylaştıran bir `wallet` oluşturmamıza da olanak tanır. - -`wallet` hakkında daha fazla bilgiyi [buradan](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets); dağıtım fonksiyonu hakkında daha fazla bilgiyi [buradan okuyabilirsiniz](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts). - -Cüzdanımızın bakiyesini kontrol etmek için basit bir test yazalım. Sözleşmemiz sırasında 1000 değerini gönderdiğimizden, cüzdanımızın bakiyesi ilk testte kontrol edebileceğimiz 1000 token olmalıdır. - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -Testi çalıştırmak için `yarn test` kullanın - -### 4.3. Adım: Olaylar yayma [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -Bu öğreticide size `Waffle`'ın en kullanışlı eşleyicilerini göstermek istiyorum, ilkiyle başlayalım. - -`Waffle`, hangi olayların nerede yayıldığını test etmemizi sağlar. - -Bu öğreticide, sözleşmemizin `transfer` yöntemini test edeceğim. - -Bu testte, bir cüzdandan diğerine transfer yapacağım ve `Transfer` olayının çağrılıp çağrılmadığını kontrol edeceğim. - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -Ayrıca, bu eşleyicinin büyük bir avantajı, testimize `withArgs` ekleyerek bu olayın hangi argümanlarla çağrıldığını kontrol edebilmemizdir. - -Bu, fonksiyonumuzun doğru çağrıldığından emin olmamızı sağlayacaktır! - -### 4.4. Adım: Mesaj ile geri döndürün [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle`, hangi mesajla geri dönüldüğünü test etmemizi sağlar. - -Bunu kontrol etmek için testimizde `revertedWith` eşleyicisini kullanacağız. - -Cüzdanımızdakinden daha fazla bir tutarda transfer yapacağımız bir test yazabiliriz. Ardından, işlemin tam mesajla geri dönüp dönmediğini kontrol edeceğiz! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### 4.5. Adım: Change-token-balance (Token bakiyesini değiştir) [Belge bağlantısı](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle`, cüzdanların bakiyelerindeki değişiklikleri kontrol etmemizi sağlar! - -Bakiye değişikliğini kontrol etmek için `changeTokenBalance` eşleyicisini veya birden fazla hesap için `changeTokenBalances`'ı kullanabiliriz. - -Eşleyici, `numbers`, `strings` ve `BigNumbers`'ı bir bakiye değişikliği olarak kabul edebilirken, adres bir cüzdan veya sözleşme olarak belirtilmelidir. - -Sıradaki testi yazalım: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -Yukarıdakiler, tek bir cüzdan için bir testtir. - -Ve birden fazla cüzdan için bir sonraki: - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -İşlemin geri çağırma (çağrıdan önce bakiyeyi kontrol etmemiz gerekiyor) veya işlem yanıtı olarak iletilmesi bekleniyor. - -## Tebrikler {#congratulations} - -**Tebrikler! Öğreticimi tamamladınız. Waffle ile akıllı sözleşmeleri test etme yolunda ilk büyük adımınızı attınız.** - -**Bu öğreticideki kodu [burada](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website) bulabilirsiniz.** - -**`Waffle` hakkında daha fazla belge [burada](https://getwaffle.io) mevcuttur.** diff --git a/public/content/translations/tr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/tr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 6749ab5b2f6..00000000000 --- a/public/content/translations/tr/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: Dinamik taklit ve sözleşme çağrılarını test etme" -description: "Dinamik taklit kullanmak ve sözleşme çağrılarını test etmek için gelişmiş Waffle öğreticisi" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "akıllı kontratlar", - "solidity", - "test etmek", - "taklit etme" - ] -skill: intermediate -lang: tr -published: 2020-11-14 ---- - -## Bu öğretici ne hakkında? {#what-is-this-tutorial-about} - -Bu öğreticide şunları nasıl yapacağınızı öğreneceksiniz: - -- dinamik taklit kullanma -- akıllı sözleşmeler arasındaki etkileşimleri test etme - -Varsayımlar: - -- `Solidity`'de basit bir akıllı sözleşme yazmayı zaten biliyorsunuz -- `JavaScript` ve `TypeScript`'e aşinasınız -- diğer `Waffle` öğreticilerini tamamladınız veya bu konuda bir iki şey biliyorsunuz - -## Dinamik taklit {#dynamic-mocking} - -Dinamik taklit neden yararlıdır? Entegrasyon testleri yerine birim testleri yazmamıza olanak tanır. Bu ne anlama geliyor? Bu, akıllı sözleşmelerin bağımlılıkları hakkında endişelenmemize gerek olmadığı anlamına gelir, dolayısıyla hepsini tamamen izole bir şekilde test edebiliriz. Bunu tam olarak nasıl yapabileceğinizi size göstereyim. - -### **1. Proje** {#1-project} - -Başlamadan önce basit bir node.js projesi hazırlamamız gerekiyor: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# veya npm kullanıyorsanız -npm init -``` - -TypeScript ve test bağımlılıklarını (mocha ve chai) ekleyerek başlayalım: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# veya npm kullanıyorsanız -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Şimdi `Waffle` ve `ethers` ekleyelim: - -```bash -yarn add --dev ethereum-waffle ethers -# veya npm kullanıyorsanız -npm install ethereum-waffle ethers --save-dev -``` - -Proje yapınız şimdi şöyle görünmelidir: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Akıllı sözleşme** {#2-smart-contract} - -Dinamik taklit etmeye başlamak için bağımlılıkları olan bir akıllı sözleşmeye ihtiyacımız var. Endişelenmeyin, bu konuyu ele alacağız! - -İşte tek amacı zengin olup olmadığımızı kontrol etmek olan `Solidity` ile yazılmış basit bir akıllı sözleşme. Yeterli token'ımız olup olmadığını kontrol etmek için bir ERC20 token'ı kullanır. Bunu `./contracts/AmIRichAlready.sol` içine koyun. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Dinamik taklit kullanmak istediğimizden, ERC20'nin tamamına ihtiyacımız yok; bu yüzden yalnızca tek bir fonksiyona sahip olan IERC20 arayüzünü kullanıyoruz. - -Bu sözleşmeyi derleme zamanı! Bunun için `Waffle` kullanacağız. İlk olarak, derleme seçeneklerini belirten basit bir `waffle.json` yapılandırma dosyası oluşturacağız. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Artık Waffle ile sözleşmeyi derlemeye hazırız: - -```bash -npx waffle -``` - -Kolay, değil mi? `build/` klasöründe sözleşmeye ve arayüze karşılık gelen iki dosya belirdi. Bunları daha sonra test için kullanacağız. - -### **3. Test etme** {#3-testing} - -Asıl testi yapmak için `AmIRichAlready.test.ts` adında bir dosya oluşturalım. Öncelikle, içe aktarma işlemlerini halletmeliyiz. Bunlara daha sonra ihtiyacımız olacak: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -JS bağımlılıkları haricinde, derlenmiş sözleşmemizi ve arayüzümüzü de içe aktarmamız gerekiyor: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -`Waffle`, test için `chai` kullanır. Ancak, bunu kullanmadan önce Waffle'ın eşleştiricilerini `chai`'nin kendisine enjekte etmemiz gerekir: - -```typescript -use(solidity) -``` - -Her testten önce sözleşmenin durumunu sıfırlayacak olan `beforeEach()` fonksiyonunu uygulamamız gerekiyor. Önce orada neye ihtiyacımız olacağını düşünelim. Bir sözleşmeyi dağıtmak için iki şeye ihtiyacımız var: bir cüzdan ve `AmIRichAlready` sözleşmesine argüman olarak geçmek için dağıtılmış bir ERC20 sözleşmesi. - -İlk olarak bir cüzdan oluşturalım: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Ardından bir ERC20 sözleşmesi dağıtmamız gerekiyor. İşte işin zor kısmı: Elimizde sadece bir arayüz var. İşte bu noktada Waffle imdadımıza yetişiyor. `Waffle`, yalnızca arayüzün _abi_'sini kullanarak bir sözleşme oluşturan sihirli bir `deployMockContract()` fonksiyonuna sahiptir: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Artık hem cüzdan hem de dağıtılmış ERC20 ile `AmIRichAlready` sözleşmesini dağıtmaya devam edebiliriz: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -Böylece `beforeEach()` fonksiyonumuz tamamlanmış oldu. Şu ana kadar `AmIRichAlready.test.ts` dosyanız şöyle görünmelidir: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -`AmIRichAlready` sözleşmesi için ilk testimizi yazalım. Sizce testimiz ne hakkında olmalı? Evet, haklısınız! Zaten zengin olup olmadığımızı kontrol etmeliyiz :) - -Fakat bir saniye bekleyin. Taklit sözleşmemiz hangi değerleri döndüreceğini nasıl bilecek? `balanceOf()` fonksiyonu için herhangi bir mantık uygulamadık. Waffle bu konuda da yardımcı olabilir. Taklit sözleşmemizde artık bazı yeni havalı şeyler var: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Bu bilgiyle nihayet ilk testimizi yazabiliriz: - -```typescript -it("cüzdanda 1.000.000'dan az token varsa false değerini döndürür", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Bu testi parçalara ayıralım: - -1. Taklit ERC20 sözleşmemizi her zaman 999.999 token'lık bir bakiye döndürecek şekilde ayarlıyoruz. -2. `contract.check()` yönteminin `false` döndürüp döndürmediğini kontrol edin. - -Canavarı ateşlemeye hazırız: - -![Geçen bir test](./test-one.png) - -Test çalışıyor, ama... hâlâ geliştirilebilecek bazı yönleri var. `balanceOf()` fonksiyonu her zaman 99999 değerini döndürecektir. Tıpkı gerçek bir sözleşmede olduğu gibi, fonksiyonun bir değer döndürmesi gereken bir cüzdan belirterek bunu iyileştirebiliriz: - -```typescript -it("cüzdanda 1.000.001'den az token varsa false değerini döndürür", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Şimdiye kadar sadece yeterince zengin olmadığımız durumu test ettik. Şimdi de tam tersini test edelim: - -```typescript -it("cüzdanda en az 1.000.001 token varsa true değerini döndürür", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Testleri çalıştırın... - -![Geçen iki test](test-two.png) - -...ve işte oldu! Sözleşmemiz istendiği gibi çalışıyor gibi görünüyor :) - -## Sözleşme çağrılarını test etme {#testing-contract-calls} - -Şimdiye kadar yaptıklarımızı özetleyelim. `AmIRichAlready` sözleşmemizin işlevselliğini test ettik ve düzgün çalışıyor gibi görünüyor. Bu, işimizin bittiği anlamına gelir, değil mi? Tam olarak değil! Waffle, sözleşmemizi daha da ileri düzeyde test etmemize olanak tanır. Peki ama tam olarak nasıl? `Waffle`'ın araç setinde `calledOnContract()` ve `calledOnContractWith()` eşleştiricileri bulunur. Bunlar, sözleşmemizin ERC20 taklit sözleşmesini çağırıp çağırmadığını kontrol etmemize olanak tanır. İşte bu eşleştiricilerden biriyle yapılmış temel bir test: - -```typescript -it("sözleşmenin ERC20 token'ında balanceOf fonksiyonunu çağırıp çağırmadığını kontrol eder", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Daha da ileri giderek bu testi size bahsettiğim diğer eşleştirici ile geliştirebiliriz: - -```typescript -it("sözleşmenin ERC20 token'ında belirli bir cüzdan ile balanceOf fonksiyonunu çağırıp çağırmadığını kontrol eder", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Testlerin doğru olup olmadığını kontrol edelim: - -![Geçen üç test](test-three.png) - -Harika, tüm testler başarılı. - -Waffle ile sözleşme çağrılarını test etmek çok kolaydır. Ve en iyi kısmı da şu. Bu eşleştiriciler hem normal hem de taklit sözleşmelerle çalışır! Bunun nedeni, `Waffle`'ın, diğer teknolojiler için popüler test kütüphanelerinde olduğu gibi kod enjekte etmek yerine, EVM çağrılarını kaydedip filtrelemesidir. - -## Bitiş Çizgisi {#the-finish-line} - -Tebrikler! Artık sözleşme çağrılarını test etmek ve sözleşmeleri dinamik olarak taklit etmek için Waffle'ı nasıl kullanacağınızı biliyorsunuz. Keşfedilecek çok daha ilginç özellikler var. Waffle'ın belgelerine göz atmanızı öneririm. - -Waffle'ın belgelerine [buradan](https://ethereum-waffle.readthedocs.io/) ulaşabilirsiniz. - -Bu öğreticinin kaynak kodunu [burada](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls) bulabilirsiniz. - -İlginizi çekebilecek diğer öğreticiler: - -- [Waffle ile akıllı sözleşmeleri test etme](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/tr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/tr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 5f969fd2878..00000000000 --- a/public/content/translations/tr/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Hardhat ve ethers ile Waffle'da merhaba dünya öğreticisi" -description: "Hardhat ve ethers.js ile ilk Waffle projenizi yapın" -author: "MiZiet" -tags: - [ - "waffle", - "akıllı kontratlar", - "solidity", - "test etmek", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: tr -published: 2020-10-16 ---- - -Bu [Waffle](https://ethereum-waffle.readthedocs.io) öğreticisinde, [hardhat](https://hardhat.org/) ve [ethers.js](https://docs.ethers.io/v5/) kullanarak basit bir "Merhaba dünya" akıllı sözleşme projesinin nasıl kurulacağını öğreneceğiz. Ardından akıllı sözleşmemize nasıl yeni bir işlevsellik ekleyeceğimizi ve Waffle ile nasıl test edeceğimizi öğreneceğiz. - -Yeni bir proje oluşturarak başlayalım: - -```bash -yarn init -``` - -veya - -```bash -npm init -``` - -ve gerekli paketleri kurarak: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -veya - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Sonraki adım, `npx hardhat` komutunu çalıştırarak örnek bir hardhat projesi oluşturmaktır. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Hardhat v2.0.3 sürümüne hoş geldiniz 👷‍ - -? Ne yapmak istersiniz? … -❯ Örnek bir proje oluştur -Boş bir hardhat.config.js oluştur -Çık -``` - -`Create a sample project` seçeneğini seçin - -Projemizin yapısı bu şekilde gözükmeli: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Biraz da bu dosyalardan bahsedelim: {#now-lets-talk} - -- Greeter.sol - solidity ile yazılmış akıllı sözleşmemiz; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Bir Greeter şu selamlama ile dağıtılıyor:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("'%s' olan selamlama '%s' olarak değiştiriliyor", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Akıllı sözleşmemiz üç bölüme ayrılabilir: - -1. constructor - `greeting` adında bir dize türü değişkeni bildirdiğimiz yer, -2. function greet - çağrıldığında `greeting` değerini döndüren bir fonksiyon, -3. function setGreeting - `greeting` değerini değiştirmemizi sağlayan bir fonksiyon. - -- sample-test.js - test dosyamız - -```js -describe("Greeter", function () { - it("Değiştirildiğinde yeni selamlamayı döndürmelidir", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Sonraki adım, sözleşmemizi derlemek ve testleri çalıştırmaktan oluşur: {#compiling-and-testing} - -Waffle testleri, Mocha'yı (bir test çerçevesi) ve Chai'yi (bir teyit kütüphanesi) kullanır. Tek yapmanız gereken `npx hardhat test` komutunu çalıştırmak ve aşağıdaki mesajın görünmesini beklemektir. - -```bash -✓ Değiştirildiğinde yeni selamlamayı döndürmelidir -``` - -### Şu ana kadar her şey harika görünüyor, projemize biraz daha karmaşıklık ekleyelim {#adding-complexity} - -Birinin selamlama olarak boş bir dize eklediği bir durum hayal edin. Bu sıcak bir karşılama olmazdı, değil mi? -Bunun olmamasını sağlayalım: - -Birisi boş bir dize geçtiğinde solidity'nin `revert` özelliğini kullanmak istiyoruz. İyi yanı ise bu işlevselliği Waffle'ın chai eşleştiricisi `to.be.revertedWith()` ile kolayca test edebilmemizdir. - -```js -it("Boş bir dize geçirildiğinde geri alınmalıdır", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Selamlama boş olmamalıdır" - ) -}) -``` - -Görünüşe göre yeni testimiz geçemedi: - -```bash -Bir Greeter şu selamlama ile dağıtılıyor: Hello, world! -'Hello, world!' olan selamlama 'Hola, mundo!' olarak değiştiriliyor - ✓ Değiştirildiğinde yeni selamlamayı döndürmelidir (1514ms) -Bir Greeter şu selamlama ile dağıtılıyor: Hello, world! -'Hello, world!' olan selamlama '' olarak değiştiriliyor - 1) Boş bir dize geçirildiğinde geri alınmalıdır - - - 1 geçen (2s) - 1 başarısız -``` - -Bu işlevselliği akıllı sözleşmemize uygulayalım: - -```solidity -require(bytes(_greeting).length > 0, "Selamlama boş olmamalıdır"); -``` - -Şimdi, setGreeting fonksiyonumuz bu şekilde gözüküyor: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Selamlama boş olmamalıdır"); -console.log("'%s' olan selamlama '%s' olarak değiştiriliyor", greeting, _greeting); -greeting = _greeting; -} -``` - -Tekrar testleri çalıştıralım: - -```bash -✓ Değiştirildiğinde yeni selamlamayı döndürmelidir (1467ms) -✓ Boş bir dize geçirildiğinde geri alınmalıdır (276ms) - -2 geçen (2s) -``` - -Tebrikler! Başardınız :) - -### Sonuç {#conclusion} - -Waffle, Hardhat ve ethers.js ile basit bir proje yaptık. Bir projenin nasıl kurulacağını, bir testin nasıl ekleneceğini ve yeni işlevselliklerin nasıl uygulanacağını öğrendik. - -Akıllı sözleşmelerinizi test etmek için daha fazla harika chai eşleştiricisi için [Waffle'ın resmi belgelerine](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html) göz atın. diff --git a/public/content/translations/tr/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/tr/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 7692adbb11f..00000000000 --- a/public/content/translations/tr/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Waffle kütüphanesiyle basit bir akıllı sözleşmeyi test etme" -description: "Yeni başlayanlar için öğretici" -author: Ewa Kowalska -tags: - [ - "akıllı kontratlar", - "solidity", - "Waffle", - "test etmek" - ] -skill: beginner -lang: tr -published: 2021-02-26 ---- - -## Bu öğreticide şunları öğreneceksiniz {#in-this-tutorial-youll-learn-how-to} - -- Cüzdan bakiyesindeki değişimleri test etme -- Belirtilen argümanlarla olay yayımlanmasını test etme -- Bir işlemin geri alındığını doğrulama - -## Varsayımlar {#assumptions} - -- Yeni bir JavaScript ya da TypeScript projesi oluşturabilirsiniz -- JavaScript'te testler konusunda temel deneyime sahipsiniz. -- Yarn ya da npm gibi bazı paket yöneticilerini daha önce kullandınız -- Akıllı sözleşmeler ve Solidity ile ilgili giriş seviyesinde bilgi sahibisiniz - -## Başlarken {#getting-started} - -Bu öğretici, yarn kullanarak test kurulumunu ve çalıştırmayı göstermektedir ancak npm'i tercih ederseniz de sorun olmaz - Resmi Waffle [dokümantasyonuna](https://ethereum-waffle.readthedocs.io/en/latest/index.html) yönlendiren uygun referansları sağlayacağım. - -## Bağımlılıkları Yükleme {#install-dependencies} - -Projenizin geliştirme bağımlılıklarına ethereum-waffle ve typescript bağımlılıklarını [ekleyin](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation). - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Örnek akıllı sözleşme {#example-smart-contract} - -Öğretici boyunca basit bir akıllı sözleşme örneği olan EtherSplitter üzerinde çalışacağız. Bu, herhangi birinin belirli bir miktarda wei göndermesine ve bu miktarı önceden tanımlanmış iki alıcı arasında eşit olarak bölmesine izin vermenin haricinde pek bir şey yapmaz. -Bölme işlevi, wei miktarının çift olmasını gerektirir, aksi takdirde geri alınır. Her iki alıcı için de bir wei transferi gerçekleştirir ve ardından Transfer olayını yayar. - -EtherSplitter kod parçacığını `src/EtherSplitter.sol` içine yerleştirin. - -```solidity -pragma solidity ^0.6.0;\n\ncontract EtherSplitter {\n address payable receiver1;\n address payable receiver2;\n\n event Transfer(address from, address to, uint256 amount);\n\n constructor(address payable _address1, address payable _address2) public {\n receiver1 = _address1;\n receiver2 = _address2;\n }\n\n function split() public payable {\n require(msg.value % 2 == 0, 'Tek wei miktarına izin verilmez');\n receiver1.transfer(msg.value / 2);\n emit Transfer(msg.sender, receiver1, msg.value / 2);\n receiver2.transfer(msg.value / 2);\n emit Transfer(msg.sender, receiver2, msg.value / 2);\n }\n} -``` - -## Sözleşmeyi derleme {#compile-the-contract} - -Sözleşmeyi [derlemek](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) için package.json dosyasına aşağıdaki girdiyi ekleyin: - -```json -\"scripts\": {\n \"build\": \"waffle\"\n } -``` - -Ardından, proje kök dizininde `waffle.json` Waffle yapılandırma dosyasını oluşturun ve aşağıdaki yapılandırmayı oraya yapıştırın: - -```json -{\n \"compilerType\": \"solcjs\",\n \"compilerVersion\": \"0.6.2\",\n \"sourceDirectory\": \"./src\",\n \"outputDirectory\": \"./build\"\n} -``` - -`yarn build` komutunu çalıştırın. Sonuç olarak, `build` dizini, içinde JSON formatında derlenmiş EtherSplitter sözleşmesiyle birlikte görünecektir. - -## Test kurulumu {#test-setup} - -Waffle ile test yapmak Chai eşleştiricileri ve Mocha kullanımını gerektirir, bu nedenle bunları projenize [eklemeniz](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) gerekir. `package.json` dosyanızı güncelleyin ve komut dosyaları bölümüne `test` girdisini ekleyin: - -```json -\"scripts\": {\n \"build\": \"waffle\",\n \"test\": \"export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'\"\n } -``` - -Testlerinizi [çalıştırmak](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) isterseniz, `yarn test` komutunu çalıştırmanız yeterlidir. - -## Test etme {#testing} - -Şimdi `test` dizinini ve `test\\EtherSplitter.test.ts` adlı yeni dosyayı oluşturun. -Aşağıdaki kod parçasını kopyalayın ve test dosyanıza yapıştırın. - -```ts -import { expect, use } from \"chai\"\nimport { Contract } from \"ethers\"\nimport { deployContract, MockProvider, solidity } from \"ethereum-waffle\"\nimport EtherSplitter from \"../build/EtherSplitter.json\"\n\nuse(solidity)\n\ndescribe(\"Ether Bölücü\", () => {\n const [sender, receiver1, receiver2] = new MockProvider().getWallets()\n let splitter: Contract\n\n beforeEach(async () => {\n splitter = await deployContract(sender, EtherSplitter, [\n receiver1.address,\n receiver2.address,\n ])\n })\n\n // testleri buraya ekleyin\n}) -``` - -Başlamadan önce birkaç kelime. -`MockProvider`, blokzincirinin sahte bir sürümünü sunar. Ayrıca, EtherSplitter sözleşmesini test etmek için sahte cüzdanlar da sunar. Sağlayıcıda `getWallets()` yöntemini çağırarak en fazla on cüzdan alabiliriz. Örnekte üç cüzdan alıyoruz: biri gönderici, ikisi de alıcılar için. - -Ardından, 'splitter' adında bir değişken tanımlıyoruz - bu bizim sahte EtherSplitter sözleşmemiz. `deployContract` yöntemi tarafından her bir testin yürütülmesinden önce oluşturulur. Bu yöntem, ilk parametre olarak aktarılan cüzdandan (bizim durumumuzda göndericinin cüzdanı) bir sözleşmenin dağıtımını simüle eder. İkinci parametre, test edilen sözleşmenin ABI'si ve bayt kodudur - buraya `build` dizininden derlenmiş EtherSplitter sözleşmesinin json dosyasını iletiyoruz. Üçüncü parametre, sözleşmenin oluşturucu argümanlarının bir dizisidir; bizim durumumuzda ise alıcıların iki adresidir. - -## changeBalances {#changebalances} - -İlk olarak, bölme yönteminin alıcıların cüzdan bakiyelerini gerçekten değiştirip değiştirmediğini kontrol edeceğiz. Göndericinin hesabından 50 wei bölersek, her iki alıcının bakiyesinin de 25 wei artmasını bekleriz. Waffle'ın `changeBalances` eşleştiricisini kullanacağız: - -```ts -it(\"Hesap bakiyelerini değiştirir\", async () => {\n await expect(() => splitter.split({ value: 50 })).to.changeBalances(\n [receiver1, receiver2],\n [25, 25]\n )\n}) -``` - -Eşleştiricinin ilk parametresi olarak alıcıların cüzdanlarının bir dizisini ve ikinci olarak da ilgili hesaplarda beklenen artışları içeren bir diziyi aktarırız. -Belirli bir cüzdanın bakiyesini kontrol etmek isteseydik, aşağıdaki örnekte olduğu gibi dizi geçmeyi gerektirmeyen `changeBalance` eşleştiricisini de kullanabilirdik: - -```ts -it(\"Hesap bakiyesini değiştirir\", async () => {\n await expect(() => splitter.split({ value: 50 })).to.changeBalance(\n receiver1,\n 25\n )\n}) -``` - -Hem `changeBalance` hem de `changeBalances` durumlarında, eşleştiricinin çağrıdan önceki ve sonraki bakiye durumlarına erişmesi gerektiği için bölme işlevini bir callback olarak geçtiğimizi unutmayın. - -Sonra, her wei transferi sonrası Transfer olayının yayımlanıp yayımlanmadığını test ediyoruz. Waffle'daki başka bir eşleştiriciye geçeceğiz: - -## Emit {#emit} - -```ts -it(\"İlk alıcıya yapılan transferde olayı yayar\", async () => {\n await expect(splitter.split({ value: 50 }))\n .to.emit(splitter, \"Transfer\")\n .withArgs(sender.address, receiver1.address, 25)\n})\n\nit(\"İkinci alıcıya yapılan transferde olayı yayar\", async () => {\n await expect(splitter.split({ value: 50 }))\n .to.emit(splitter, \"Transfer\")\n .withArgs(sender.address, receiver2.address, 25)\n}) -``` - -`emit` eşleştiricisi, bir sözleşmenin bir yöntemi çağırırken bir olay yayımlayıp yayımlamadığını kontrol etmemizi sağlar. `emit` eşleştiricisinin parametreleri olarak, olayı yayacağını tahmin ettiğimiz sahte sözleşmeyi ve o olayın adını belirtiriz. Bizim durumumuzda, sahte sözleşme `splitter` ve olayın adı `Transfer`'dır. Ayrıca olayın yayımlandığı argümanların kesin değerlerini de doğrulayabiliriz - olay bildirimimizin beklediği kadar argümanı `withArgs` eşleştiricisine geçiririz. EtherSplitter sözleşmesi durumunda ise, gönderici ve alıcının adresleri ile transfer edilen wei miktarını aktarırız. - -## revertedWith {#revertedwith} - -Son örnek olarak, tek sayıda wei olması durumunda işlemin geri alınıp alınmadığını kontrol edeceğiz. `revertedWith` eşleştiricisini kullanacağız: - -```ts -it(\"Wei miktarı tek olduğunda geri döner\", async () => {\n await expect(splitter.split({ value: 51 })).to.be.revertedWith(\n \"Tek wei miktarına izin verilmez\"\n )\n}) -``` - -Test geçerse, işlemin gerçekten geri alındığından emin olacağız. Ancak `require` ifadesinde geçtiğimiz mesaj ile `revertedWith` içinde beklediğimiz mesaj arasında tam bir eşleşme olmalıdır. EtherSplitter sözleşmesinin koduna geri dönersek, wei miktarı için `require` ifadesinde şu mesajı sağlıyoruz: 'Tek wei miktarına izin verilmez'. Bu, testimizde beklediğimiz mesajla eşleşir. Eğer eşit değillerse, test başarısız olacaktır. - -## Tebrikler! {#congratulations} - -Waffle ile akıllı sözleşmeleri test etmenin ilk büyük adımını tamamladınız! diff --git a/public/content/translations/uk/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/uk/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 1d73a77b509..00000000000 --- a/public/content/translations/uk/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: динамічне мокування та тестування викликів контрактів" -description: "Розширений підручник з Waffle щодо використання динамічного мокування та тестування викликів контрактів" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "Смарт-контракти", - "мова програмування", - "тестування", - "глузливий" - ] -skill: intermediate -lang: uk -published: 2020-11-14 ---- - -## Про що цей підручник? {#what-is-this-tutorial-about} - -У цьому підручнику ви дізнаєтеся, як: - -- використовувати динамічне мокування -- тестувати взаємодію між смарт-контрактами - -Припущення: - -- ви вже знаєте, як написати простий смарт-контракт на `Solidity` -- ви добре орієнтуєтеся в `JavaScript` та `TypeScript` -- ви пройшли інші підручники з `Waffle` або вже дещо про нього знаєте - -## Динамічне мокування {#dynamic-mocking} - -Чому динамічне мокування корисне? Ну, це дозволяє нам писати модульні тести замість інтеграційних тестів. Що це означає? Це означає, що нам не потрібно турбуватися про залежності смарт-контрактів, тому ми можемо тестувати їх усі в повній ізоляції. Дозвольте мені показати вам, як саме ви можете це зробити. - -### **1. Проєкт** {#1-project} - -Перш ніж розпочати, нам потрібно підготувати простий проєкт node.js: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# або якщо ви використовуєте npm -npm init -``` - -Почнімо з додавання `typescript` і тестових залежностей — `mocha` та `chai`: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# або якщо ви використовуєте npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -Тепер додамо `Waffle` та `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# або якщо ви використовуєте npm -npm install ethereum-waffle ethers --save-dev -``` - -Тепер структура вашого проєкту має виглядати так: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. Смарт-контракт** {#2-smart-contract} - -Щоб розпочати динамічне мокування, нам потрібен смарт-контракт із залежностями. Не хвилюйтеся, я про все подбав! - -Ось простий смарт-контракт, написаний на `Solidity`, єдина мета якого — перевірити, чи ми багаті. Він використовує токен ERC20, щоб перевірити, чи достатньо у нас токенів. Помістіть його в `./contracts/AmIRichAlready.sol`. - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -Оскільки ми хочемо використовувати динамічне мокування, нам не потрібен весь ERC20, тому ми використовуємо інтерфейс IERC20 лише з однією функцією. - -Час зібрати цей контракт! Для цього ми будемо використовувати `Waffle`. Спочатку ми створимо простий конфігураційний файл `waffle.json`, який визначає параметри компіляції. - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -Тепер ми готові зібрати контракт за допомогою Waffle: - -```bash -npx waffle -``` - -Легко, правда? У папці `build/` з'явилися два файли, що відповідають контракту та інтерфейсу. Ми будемо використовувати їх пізніше для тестування. - -### **3. Тестування** {#3-testing} - -Створімо файл під назвою `AmIRichAlready.test.ts` для фактичного тестування. Перш за все, нам потрібно налаштувати імпорти. Вони нам знадобляться пізніше: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -Окрім залежностей JS, нам потрібно імпортувати наш зібраний контракт та інтерфейс: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -`Waffle` використовує `chai` для тестування. Однак, перш ніж ми зможемо його використовувати, нам потрібно впровадити матчери `Waffle` у сам `chai`: - -```typescript -use(solidity) -``` - -Нам потрібно реалізувати функцію `beforeEach()`, яка скидатиме стан контракту перед кожним тестом. Давайте спочатку подумаємо, що нам там потрібно. Щоб розгорнути контракт, нам потрібні дві речі: гаманець і розгорнутий контракт ERC20, щоб передати його як аргумент контракту `AmIRichAlready`. - -Перш за все, ми створюємо гаманець: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -Тоді нам потрібно розгорнути контракт ERC20. Ось складна частина — у нас є лише інтерфейс. Саме тут `Waffle` приходить нам на допомогу. `Waffle` має магічну функцію `deployMockContract()`, яка створює контракт, використовуючи лише `_abi_` інтерфейсу: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -Тепер, маючи і гаманець, і розгорнутий ERC20, ми можемо розгортати контракт `AmIRichAlready`: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -На цьому наша функція `beforeEach()` готова. Поки що ваш файл `AmIRichAlready.test.ts` має виглядати так: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -Напишімо перший тест для контракту `AmIRichAlready`. Як ви гадаєте, про що має бути наш тест? Так, ви маєте рацію! Ми повинні перевірити, чи ми вже багаті :) - -Але почекайте секунду. Звідки наш змокований контракт знатиме, які значення повертати? Ми не реалізували жодної логіки для функції `balanceOf()`. Знову ж таки, `Waffle` може тут допомогти. Тепер наш змокований контракт має кілька нових цікавих можливостей: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -Маючи ці знання, ми нарешті можемо написати наш перший тест: - -```typescript -it("повертає false, якщо в гаманці менше ніж 1000000 токенів", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Розберемо цей тест по частинах: - -1. Ми налаштували наш змокований контракт ERC20 так, щоб він завжди повертав баланс у 999999 токенів. -2. Перевірте, чи метод `contract.check()` повертає `false`. - -Ми готові все запустити: - -![Один пройдений тест](./test-one.png) - -Отже, тест працює, але... ще є простір для вдосконалення. Функція `balanceOf()` завжди повертатиме 99999. Ми можемо покращити його, вказавши гаманець, для якого функція повинна щось повертати — так само, як справжній контракт: - -```typescript -it("повертає false, якщо в гаманці менше ніж 1000001 токенів", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -Досі ми тестували лише випадок, коли ми недостатньо багаті. Натомість протестуймо протилежний випадок: - -```typescript -it("повертає true, якщо в гаманці є щонайменше 1000001 токенів", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -Ви запускаєте тести... - -![Два пройдених тести](test-two.png) - -...і готово! Здається, наш контракт працює належним чином :) - -## Тестування викликів контрактів {#testing-contract-calls} - -Підсумуймо, що ми вже зробили. Ми протестували функціонал нашого контракту `AmIRichAlready`, і він, здається, працює належним чином. Це означає, що ми закінчили, правда? Не зовсім! `Waffle` дозволяє нам протестувати наш контракт ще глибше. Але як саме? В арсеналі `Waffle` є матчери `calledOnContract()` і `calledOnContractWith()`. Вони дозволять нам перевірити, чи наш контракт викликав змокований контракт ERC20. Ось базовий тест з одним із цих матчерів: - -```typescript -it("перевіряє, чи контракт викликав balanceOf для токена ERC20", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -Ми можемо піти ще далі й покращити цей тест за допомогою іншого матчера, про який я вам розповідав: - -```typescript -it("перевіряє, чи контракт викликав balanceOf з певним гаманцем для токена ERC20", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -Давайте перевіримо, чи правильні тести: - -![Три пройдених тести](test-three.png) - -Чудово, всі тести зелені. - -Тестувати виклики контрактів за допомогою `Waffle` дуже просто. І ось найкраща частина. Ці матчери працюють як зі звичайними, так і зі змокованими контрактами! Це тому, що `Waffle` записує та фільтрує виклики EVM, а не впроваджує код, як це відбувається в популярних бібліотеках тестування для інших технологій. - -## Фінішна пряма {#the-finish-line} - -Вітаємо! Тепер ви знаєте, як використовувати `Waffle` для тестування викликів контрактів і динамічного мокування контрактів. Є ще багато цікавих особливостей, які слід відкрити. Я рекомендую зануритися в документацію Waffle. - -Документація `Waffle` доступна [тут](https://ethereum-waffle.readthedocs.io/). - -Вихідний код для цього підручника можна знайти [тут](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls). - -Підручники, які також можуть вас зацікавити: - -- [Тестування смарт-контрактів за допомогою Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/uk/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/uk/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 4a6ac97c77d..00000000000 --- a/public/content/translations/uk/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Посібник Waffle «Привіт, світе» з Hardhat та Ethers" -description: "Створіть свій перший проєкт Waffle з Hardhat та ethers.js" -author: "MiZiet" -tags: - [ - "waffle", - "Смарт-контракти", - "мова програмування", - "тестування", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: uk -published: 2020-10-16 ---- - -У цьому посібнику з [Waffle](https://ethereum-waffle.readthedocs.io) ми дізнаємося, як налаштувати простий проєкт смарт-контракту «Привіт, світе», використовуючи [hardhat](https://hardhat.org/) та [ethers.js](https://docs.ethers.io/v5/). Потім ми дізнаємося, як додати нову функціональність до нашого смарт-контракту та як протестувати його за допомогою Waffle. - -Давайте розпочнемо зі створення нового проєкту: - -```bash -yarn init -``` - -або - -```bash -npm init -``` - -та встановлення необхідних пакетів: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -або - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -Наступний крок — створення зразка проєкту Hardhat за допомогою команди `npx hardhat`. - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Ласкаво просимо до Hardhat v2.0.3 👷‍ - -? Що ви хочете зробити? … -❯ Створити зразок проєкту -Створити порожній hardhat.config.js -Вийти -``` - -Виберіть `Створити зразок проєкту` - -Структура нашого проєкту має виглядати так: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### Тепер поговоримо про деякі з цих файлів: {#now-lets-talk} - -- Greeter.sol — наш смарт-контракт, написаний мовою Solidity; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Розгортання Greeter з привітанням:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Зміна привітання з '%s' на '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -Наш смарт-контракт можна розділити на три частини: - -1. конструктор — у ньому ми оголошуємо змінну типу string під назвою `greeting`, -2. функція greet — функція, яка під час виклику повертає `greeting`, -3. функція setGreeting — функція, яка дає змогу змінювати значення `greeting`. - -- sample-test.js — наш файл тестів - -```js -describe("Greeter", function () { - it("Має повертати нове привітання після його зміни", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### Наступний крок — компіляція нашого контракту та запуск тестів: {#compiling-and-testing} - -Тести Waffle використовують Mocha (фреймворк для тестування) з Chai (бібліотека тверджень). Все, що потрібно зробити, це виконати `npx hardhat test` і дочекатися появи наступного повідомлення. - -```bash -✓ Має повертати нове привітання після його зміни -``` - -### Поки що все чудово, додамо трохи складності до нашого проєкту {#adding-complexity} - -Уявіть ситуацію, коли хтось додає порожній рядок як привітання. Це було б не дуже тепле привітання, чи не так? -Переконаємося, що цього не станеться: - -Ми хочемо використовувати `revert` з Solidity, коли хтось передає порожній рядок. Добре, що ми можемо легко протестувати цю функціональність за допомогою зіставлення `to.be.revertedWith()` з Chai від Waffle. - -```js -it("Має скасовувати операцію в разі передавання порожнього рядка", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Привітання не повинно бути порожнім" - ) -}) -``` - -Схоже, наш новий тест не пройшов: - -```bash -Розгортання Greeter з привітанням: Hello, world! -Зміна привітання з 'Hello, world!' на 'Hola, mundo!' - ✓ Має повертати нове привітання після його зміни (1514ms) -Розгортання Greeter з привітанням: Hello, world! -Зміна привітання з 'Hello, world!' на '' - 1) Має скасовувати операцію в разі передавання порожнього рядка - - - 1 пройдено (2с) - 1 не пройдено -``` - -Реалізуймо цю функціональність у нашому смарт-контракті: - -```solidity -require(bytes(_greeting).length > 0, "Привітання не повинно бути порожнім"); -``` - -Тепер наша функція setGreeting виглядає так: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Привітання не повинно бути порожнім"); -console.log("Зміна привітання з '%s' на '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -Запустімо тести знову: - -```bash -✓ Має повертати нове привітання після його зміни (1467ms) -✓ Має скасовувати операцію в разі передавання порожнього рядка (276ms) - -2 пройдено (2с) -``` - -Вітаємо! Ви впоралися :) - -### Висновок {#conclusion} - -Ми створили простий проєкт за допомогою Waffle, Hardhat та ethers.js. Ми дізналися, як налаштовувати проєкт, додавати тест і реалізовувати нову функціональність. - -Щоб знайти більше чудових зіставлень Chai для тестування ваших смарт-контрактів, перегляньте [офіційну документацію Waffle](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html). diff --git a/public/content/translations/uk/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/uk/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 5c5227c40ab..00000000000 --- a/public/content/translations/uk/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: "Тестування простого смарт-контракту з бібліотекою Waffle" -description: "Підручник для початківців" -author: Ewa Kowalska -tags: - [ - "Смарт-контракти", - "мова програмування", - "Waffle", - "тестування" - ] -skill: beginner -lang: uk -published: 2021-02-26 ---- - -## У цьому підручнику ви дізнаєтеся, як {#in-this-tutorial-youll-learn-how-to} - -- Перевіряти зміни балансу гаманця -- Тестувати емісію подій із зазначеними аргументами -- Перевіряти, що транзакцію було повернуто - -## Припущення {#assumptions} - -- Ви можете створити новий проєкт на JavaScript або TypeScript -- У вас є базовий досвід роботи з тестами в JavaScript -- Ви використовували менеджери пакунків, як-от yarn або npm -- Ви володієте базовими знаннями про смарт-контракти та Solidity - -## Початок роботи {#getting-started} - -У цьому посібнику демонструється налаштування та запуск тестування за допомогою yarn, але ви можете використовувати й npm. Я надам відповідні посилання на офіційну [документацію](https://ethereum-waffle.readthedocs.io/en/latest/index.html) Waffle. - -## Встановлення залежностей {#install-dependencies} - -[Додайте](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) залежності ethereum-waffle та typescript до залежностей для розробки (dev dependencies) вашого проєкту. - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## Приклад смарт-контракту {#example-smart-contract} - -Під час цього посібника ми будемо працювати над простим прикладом смарт-контракту — EtherSplitter. Він мало що робить, окрім як дозволяє будь-кому надіслати трохи wei та розділити їх порівну між двома попередньо визначеними одержувачами. -Функція `split` вимагає, щоб кількість wei була парною, інакше транзакція буде повернута. Для обох одержувачів він виконує переказ wei, після чого відбувається емісія події `Transfer`. - -Розмістіть фрагмент коду EtherSplitter у `src/EtherSplitter.sol`. - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## Компіляція контракту {#compile-the-contract} - -Щоб [скомпілювати](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) контракт, додайте наступний запис до файлу package.json: - -```json -"scripts": { - "build": "waffle" - } -``` - -Далі створіть файл конфігурації Waffle у кореневому каталозі проєкту — `waffle.json` — а потім вставте туди таку конфігурацію: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -Запустіть `yarn build`. У результаті з’явиться каталог `build` зі скомпільованим контрактом EtherSplitter у форматі JSON. - -## Налаштування тестування {#test-setup} - -Тестування за допомогою Waffle вимагає використання Chai matchers та Mocha, тому вам потрібно [додати](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) їх до свого проєкту. Оновіть файл package.json і додайте запис `test` у розділ `scripts`: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -Якщо ви хочете [виконати](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) свої тести, просто запустіть `yarn test`. - -## Тестування {#testing} - -Тепер створіть каталог `test` і створіть новий файл `test\EtherSplitter.test.ts`. -Скопіюйте фрагмент коду нижче та вставте його в наш файл тестування. - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Розподілювач ефіру", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // додайте сюди тести -}) -``` - -Кілька слів перед тим, як ми почнемо. -`MockProvider` створює імітовану версію блокчейну. Він також надає імітовані гаманці, які слугуватимуть нам для тестування контракту EtherSplitter. Ми можемо отримати до десяти гаманців, викликавши метод `getWallets()` у провайдера. У цьому прикладі ми отримуємо три гаманці: для відправника та для двох одержувачів. - -Далі ми оголошуємо змінну з назвою `splitter` — це наш імітований контракт EtherSplitter. Він створюється перед кожним виконанням окремого тесту за допомогою методу `deployContract`. Цей метод імітує розгортання контракту з гаманця, переданого як перший параметр (у нашому випадку — гаманець відправника). Другий параметр — це ABI та байт-код тестованого контракту. Ми передаємо туди JSON-файл скомпільованого контракту EtherSplitter з каталогу `build`. Третій параметр — це масив з аргументами конструктора контракту, якими в нашому випадку є дві адреси одержувачів. - -## Зміна балансів {#changebalances} - -Спочатку ми перевіримо, чи метод `split` дійсно змінює баланси гаманців одержувачів. Якщо ми розділимо 50 wei з рахунку відправника, то очікуємо, що баланси обох одержувачів збільшаться на 25 wei. Ми будемо використовувати матчер `changeBalances` з Waffle: - -```ts -it("Змінює баланси рахунків", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -Як перший параметр матчера ми передаємо масив гаманців одержувачів, а як другий — масив очікуваних приростів на відповідних рахунках. -Якби ми хотіли перевірити баланс одного конкретного гаманця, ми могли б також використати матчер `changeBalance`, який не вимагає передачі масивів, як у прикладі нижче: - -```ts -it("Змінює баланс рахунку", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -Зверніть увагу, що в обох випадках (`changeBalance` і `changeBalances`) ми передаємо функцію `split` як функцію зворотного виклику, оскільки матчеру потрібно отримати доступ до стану балансів до та після виклику. - -Далі ми перевіримо, чи була згенерована подія `Transfer` після кожного переказу wei. Ми звернемося до іншого матчера з Waffle: - -## Emit {#emit} - -```ts -it("Генерує подію під час переказу першому одержувачу", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Генерує подію під час переказу другому одержувачу", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -Матчер `emit` дозволяє нам перевірити, чи згенерував контракт подію під час виклику методу. Як параметри для матчера `emit`, ми надаємо імітований контракт, який, за нашими прогнозами, згенерує подію, разом із назвою цієї події. У нашому випадку імітований контракт — це `splitter`, а назва події — `Transfer`. Ми також можемо перевірити точні значення аргументів, з якими була згенерована подія — ми передаємо стільки аргументів до матчера `withArgs`, скільки очікує наше оголошення події. У випадку контракту EtherSplitter, ми передаємо адреси відправника та одержувача разом із сумою переказаних wei. - -## revertedWith {#revertedwith} - -В останньому прикладі ми перевіримо, чи була транзакція повернута у випадку непарної кількості wei. Ми будемо використовувати матчер `revertedWith`: - -```ts -it("Повертає транзакцію, якщо кількість wei непарна", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -Тест, якщо він пройде успішно, запевнить нас, що транзакція дійсно була повернута. Однак, також має бути точна відповідність між повідомленнями, які ми передали в операторі `require`, і повідомленням, яке ми очікуємо в `revertedWith`. Якщо ми повернемося до коду контракту EtherSplitter, то в операторі `require` для суми wei ми надаємо повідомлення: 'Uneven wei amount not allowed'. Це відповідає повідомленню, яке ми очікуємо в нашому тесті. Якби вони не були однаковими, тест не пройшов би. - -## Вітаємо! {#congratulations} - -Ви зробили свій перший великий крок до тестування смарт-контрактів за допомогою Waffle! diff --git a/public/content/translations/ur/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/ur/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 7141c102eb4..00000000000 --- a/public/content/translations/ur/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,300 +0,0 @@ ---- -title: "Waffle: متحرک نقالی اور کانٹریکٹ کالز کی جانچ" -description: "متحرک نقالی اور کانٹریکٹ کالز کی جانچ کے استعمال کے لیے ایک اعلی درجے کا Waffle ٹیوٹوریل" -author: "Daniel Izdebski" -tags: - [ - "waffle", - "اسمارٹ معاہدات", - "solidity", - "testing", - "mocking" - ] -skill: intermediate -lang: ur-in -published: 2020-11-14 ---- - -## یہ ٹیوٹوریل کس بارے میں ہے؟ {#what-is-this-tutorial-about} - -اس ٹیوٹوریل میں آپ سیکھیں گے کہ کیسے: - -- متحرک نقالی کا استعمال -- اسمارٹ کانٹریکٹس کے درمیان تعاملات کی جانچ کریں - -مفروضے: - -- آپ پہلے ہی جانتے ہیں کہ `Solidity` میں ایک سادہ اسمارٹ کانٹریکٹ کیسے لکھنا ہے -- آپ `JavaScript` اور `TypeScript` سے واقف ہیں -- آپ نے دوسرے `Waffle` ٹیوٹوریلز کیے ہیں یا اس کے بارے میں کچھ جانتے ہیں - -## متحرک نقالی {#dynamic-mocking} - -متحرک نقالی کیوں مفید ہے؟ خیر، یہ ہمیں انٹیگریشن ٹیسٹ کے بجائے یونٹ ٹیسٹ لکھنے کی اجازت دیتا ہے۔ اس کا کیا مطلب ہے؟ اس کا مطلب ہے کہ ہمیں اسمارٹ کانٹریکٹس کے انحصار کے بارے میں فکر کرنے کی ضرورت نہیں ہے، اس طرح ہم ان سب کو مکمل تنہائی میں جانچ سکتے ہیں۔ آئیے میں آپ کو دکھاتا ہوں کہ آپ اسے ٹھیک ٹھیک کیسے کر سکتے ہیں۔ - -### **1.** پروجیکٹ\*\* {#1-project} - -شروع کرنے سے پہلے ہمیں ایک سادہ node.js پروجیکٹ تیار کرنے کی ضرورت ہے: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -آئیے ٹائپ اسکرپٹ اور ٹیسٹ ڈیپینڈنسیز - mocha اور chai شامل کرنے کے ساتھ شروع کرتے ہیں: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -اب آئیے `Waffle` اور `ethers` شامل کریں: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -آپ کے پروجیکٹ کی ساخت اب اس طرح نظر آنی چاہئے: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2.** اسمارٹ کانٹریکٹ\*\* {#2-smart-contract} - -متحرک نقالی شروع کرنے کے لیے، ہمیں انحصار کے ساتھ ایک اسمارٹ کانٹریکٹ کی ضرورت ہے۔ فکر نہ کریں، میں نے آپ کا کام آسان کر دیا ہے! - -یہاں `Solidity` میں لکھا گیا ایک سادہ اسمارٹ کانٹریکٹ ہے جس کا واحد مقصد یہ جانچنا ہے کہ کیا ہم امیر ہیں۔ یہ جانچنے کے لیے ERC20 ٹوکن کا استعمال کرتا ہے کہ آیا ہمارے پاس کافی ٹوکن ہیں۔ اسے `./contracts/AmIRichAlready.sol` میں ڈالیں۔ - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -چونکہ ہم متحرک نقالی کا استعمال کرنا چاہتے ہیں اس لیے ہمیں پورے ERC20 کی ضرورت نہیں ہے، یہی وجہ ہے کہ ہم صرف ایک فنکشن کے ساتھ IERC20 انٹرفیس کا استعمال کر رہے ہیں۔ - -اب اس کانٹریکٹ کو بنانے کا وقت ہے! اس کے لیے ہم `Waffle` کا استعمال کریں گے۔ سب سے پہلے، ہم ایک سادہ `waffle.json` کنفگ فائل بنانے جا رہے ہیں جو کمپائلیشن کے اختیارات کی وضاحت کرتی ہے۔ - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -اب ہم Waffle کے ساتھ کانٹریکٹ بنانے کے لیے تیار ہیں: - -```bash -npx waffle -``` - -آسان ہے، ہے نا؟ `build/` فولڈر میں کانٹریکٹ اور انٹرفیس سے مطابقت رکھنے والی دو فائلیں ظاہر ہوئیں۔ ہم انہیں بعد میں جانچ کے لیے استعمال کریں گے۔ - -### **3.** جانچ\*\* {#3-testing} - -آئیے اصل جانچ کے لیے `AmIRichAlready.test.ts` نامی ایک فائل بنائیں۔ سب سے پہلے، ہمیں امپورٹس کو سنبھالنا ہوگا۔ ہمیں بعد میں ان کی ضرورت ہوگی: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -JS ڈیپینڈنسیز کے علاوہ، ہمیں اپنے بنائے ہوئے کانٹریکٹ اور انٹرفیس کو امپورٹ کرنے کی ضرورت ہے: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle جانچ کے لیے `chai` کا استعمال کرتا ہے۔ تاہم، اس کا استعمال کرنے سے پہلے، ہمیں Waffle کے میچرز کو خود chai میں انجیکٹ کرنا ہوگا: - -```typescript -use(solidity) -``` - -ہمیں `beforeEach()` فنکشن کو لاگو کرنے کی ضرورت ہے جو ہر ٹیسٹ سے پہلے کانٹریکٹ کی حالت کو ری سیٹ کرے گا۔ آئیے پہلے سوچیں کہ ہمیں وہاں کیا ضرورت ہے۔ ایک کانٹریکٹ کو تعینات کرنے کے لیے ہمیں دو چیزوں کی ضرورت ہے: ایک والیٹ اور ایک تعینات شدہ ERC20 کانٹریکٹ تاکہ اسے `AmIRichAlready` کانٹریکٹ کے لیے ایک دلیل کے طور پر پاس کیا جا سکے۔ - -سب سے پہلے ہم ایک والیٹ بناتے ہیں: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -پھر ہمیں ایک ERC20 کانٹریکٹ تعینات کرنے کی ضرورت ہے۔ یہاں مشکل حصہ ہے - ہمارے پاس صرف ایک انٹرفیس ہے۔ یہ وہ حصہ ہے جہاں Waffle ہمیں بچانے کے لیے آتا ہے۔ Waffle میں ایک جادوئی `deployMockContract()` فنکشن ہے جو صرف انٹرفیس کے _abi_ کا استعمال کرتے ہوئے ایک کانٹریکٹ بناتا ہے: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -اب والیٹ اور تعینات شدہ ERC20 دونوں کے ساتھ، ہم آگے بڑھ کر `AmIRichAlready` کانٹریکٹ تعینات کر سکتے ہیں: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -ان سب کے ساتھ، ہمارا `beforeEach()` فنکشن ختم ہو گیا ہے۔ اب تک آپ کی `AmIRichAlready.test.ts` فائل اس طرح نظر آنی چاہیے: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -آئیے `AmIRichAlready` کانٹریکٹ کے لیے پہلا ٹیسٹ لکھیں۔ آپ کے خیال میں ہمارا ٹیسٹ کس بارے میں ہونا چاہئے؟ ہاں، آپ صحیح ہیں! ہمیں یہ جانچنا چاہئے کہ کیا ہم پہلے ہی امیر ہیں :) - -لیکن ایک سیکنڈ رکیں۔ ہمارا نقلی کانٹریکٹ کیسے جانے گا کہ کون سی قدریں واپس کرنی ہیں؟ ہم نے `balanceOf()` فنکشن کے لیے کوئی منطق نافذ نہیں کی ہے۔ ایک بار پھر، Waffle یہاں مدد کر سکتا ہے۔ ہمارے نقلی کانٹریکٹ میں اب کچھ نئی فینسی چیزیں ہیں: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -اس علم کے ساتھ ہم آخر کار اپنا پہلا ٹیسٹ لکھ سکتے ہیں: - -```typescript -it("returns false if the wallet has less than 1000000 tokens", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -آئیے اس ٹیسٹ کو حصوں میں تقسیم کرتے ہیں: - -1. ہم نے اپنے نقلی ERC20 کانٹریکٹ کو ہمیشہ 999999 ٹوکنز کا بیلنس واپس کرنے کے لیے سیٹ کیا ہے۔ -2. جانچیں کہ کیا `contract.check()` طریقہ `false` واپس کرتا ہے۔ - -ہم اسے چلانے کے لیے تیار ہیں: - -![ایک ٹیسٹ پاس ہو رہا ہے](./test-one.png) - -تو ٹیسٹ کام کرتا ہے، لیکن... اب بھی بہتری کی گنجائش ہے۔ `balanceOf()` فنکشن ہمیشہ 999999 واپس کرے گا۔ ہم ایک والیٹ کی وضاحت کرکے اسے بہتر بنا سکتے ہیں جس کے لئے فنکشن کو کچھ واپس کرنا چاہئے - بالکل ایک حقیقی کانٹریکٹ کی طرح: - -```typescript -it("returns false if the wallet has less than 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -اب تک، ہم نے صرف اس معاملے کی جانچ کی ہے جہاں ہم کافی امیر نہیں ہیں۔ اس کے بجائے آئیے اس کے برعکس جانچتے ہیں: - -```typescript -it("returns true if the wallet has at least 1000001 tokens", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -آپ ٹیسٹ چلاتے ہیں... - -![دو ٹیسٹ پاس ہو رہے ہیں](test-two.png) - -... اور یہ ہو گیا! ہمارا کانٹریکٹ ارادے کے مطابق کام کرتا نظر آتا ہے :) - -## کانٹریکٹ کالز کی جانچ {#testing-contract-calls} - -آئیے اس کا خلاصہ کریں جو ہم نے اب تک کیا ہے۔ ہم نے اپنے `AmIRichAlready` کانٹریکٹ کی فعالیت کی جانچ کی ہے اور یہ ٹھیک سے کام کرتا نظر آتا ہے۔ اس کا مطلب ہے کہ ہمارا کام ہو گیا، ٹھیک ہے؟ بالکل نہیں! Waffle ہمیں اپنے کانٹریکٹ کو مزید جانچنے کی اجازت دیتا ہے۔ لیکن ٹھیک ٹھیک کیسے؟ خیر، Waffle کے آرسینل میں `calledOnContract()` اور `calledOnContractWith()` میچرز ہیں۔ وہ ہمیں یہ جانچنے کی اجازت دیں گے کہ آیا ہمارے کانٹریکٹ نے ERC20 نقلی کانٹریکٹ کو کال کیا ہے۔ ان میچرز میں سے ایک کے ساتھ ایک بنیادی ٹیسٹ یہ ہے: - -```typescript -it("checks if contract called balanceOf on the ERC20 token", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -ہم مزید آگے جا سکتے ہیں اور اس ٹیسٹ کو دوسرے میچر کے ساتھ بہتر بنا سکتے ہیں جس کے بارے میں میں نے آپ کو بتایا تھا: - -```typescript -it("checks if contract called balanceOf with certain wallet on the ERC20 token", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -آئیے جانچتے ہیں کہ کیا ٹیسٹ درست ہیں: - -![تین ٹیسٹ پاس ہو رہے ہیں](test-three.png) - -بہت اچھا، تمام ٹیسٹ پاس ہو گئے ہیں۔ - -Waffle کے ساتھ کانٹریکٹ کالز کی جانچ بہت آسان ہے۔ اور یہاں بہترین حصہ ہے۔ یہ میچرز عام اور نقلی دونوں کانٹریکٹس کے ساتھ کام کرتے ہیں! یہ اس لیے ہے کہ Waffle کوڈ انجیکٹ کرنے کے بجائے EVM کالز کو ریکارڈ اور فلٹر کرتا ہے، جیسا کہ دیگر ٹیکنالوجیز کے لیے مقبول ٹیسٹنگ لائبریریوں کا معاملہ ہے۔ - -## اختتامی لکیر {#the-finish-line} - -مبارک ہو! اب آپ جانتے ہیں کہ کانٹریکٹ کالز کی جانچ کرنے اور کانٹریکٹس کو متحرک طور پر نقل کرنے کے لیے Waffle کا استعمال کیسے کرنا ہے۔ دریافت کرنے کے لیے اور بھی بہت سی دلچسپ خصوصیات ہیں۔ میں Waffle کی دستاویزات میں گہرائی سے جانے کی تجویز کرتا ہوں۔ - -Waffle کی دستاویزات [یہاں](https://ethereum-waffle.readthedocs.io/) دستیاب ہے۔ - -اس ٹیوٹوریل کا سورس کوڈ [یہاں](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls) پایا جا سکتا ہے۔ - -ٹیوٹوریلز جن میں آپ کو بھی دلچسپی ہو سکتی ہے: - -- [Waffle کے ساتھ اسمارٹ کانٹریکٹس کی جانچ](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/ur/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/ur/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index c59d8ed42a4..00000000000 --- a/public/content/translations/ur/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "ہارڈ ہیٹ اور ایتھرس کے ساتھ وافل کا ہیلو ورلڈ ٹیوٹوریل" -description: "ہارڈ ہیٹ اور ethers.js کے ساتھ اپنا پہلا وافل پروجیکٹ بنائیں" -author: "MiZiet" -tags: - [ - "waffle", - "اسمارٹ معاہدات", - "solidity", - "testing", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: ur-in -published: 2020-10-16 ---- - -اس [Waffle](https://ethereum-waffle.readthedocs.io) ٹیوٹوریل میں، ہم [hardhat](https://hardhat.org/) اور [ethers.js](https://docs.ethers.io/v5/) کا استعمال کرتے ہوئے ایک سادہ "ہیلو ورلڈ" اسمارٹ کنٹریکٹ پروجیکٹ سیٹ اپ کرنے کا طریقہ سیکھیں گے۔ پھر ہم سیکھیں گے کہ اپنے اسمارٹ کنٹریکٹ میں ایک نئی فنکشنلٹی کیسے شامل کی جائے اور وافل کے ساتھ اس کی جانچ کیسے کی جائے۔ - -آئیے ایک نیا پروجیکٹ بنا کر شروعات کریں: - -```bash -yarn init -``` - -یا - -```bash -npm init -``` - -اور مطلوبہ پیکیجز انسٹال کریں: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -یا - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -اگلا مرحلہ `npx hardhat` چلا کر ایک نمونہ ہارڈ ہیٹ پروجیکٹ بنانا ہے۔ - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -`Create a sample project` کو منتخب کریں - -ہمارے پروجیکٹ کی ساخت کچھ اس طرح نظر آنی چاہیے: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### اب ان میں سے کچھ فائلوں کے بارے میں بات کرتے ہیں: {#now-lets-talk} - -- Greeter.sol - ہمارا اسمارٹ کنٹریکٹ جو سولڈیٹی میں لکھا گیا ہے؛ - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -ہمارے اسمارٹ کنٹریکٹ کو تین حصوں میں تقسیم کیا جا سکتا ہے: - -1. کنسٹرکٹر - جہاں ہم `greeting` نامی ایک سٹرنگ ٹائپ متغیر کا اعلان کرتے ہیں، -2. فنکشن greet - ایک فنکشن جو کال کیے جانے پر `greeting` واپس کرے گا، -3. فنکشن setGreeting - ایک فنکشن جو ہمیں `greeting` کی قدر کو تبدیل کرنے کی اجازت دیتا ہے۔ - -- sample-test.js - ہماری ٹیسٹ فائل - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### اگلا مرحلہ ہمارے کنٹریکٹ کو کمپائل کرنے اور ٹیسٹ چلانے پر مشتمل ہے: {#compiling-and-testing} - -وافل ٹیسٹ موچا (ایک ٹیسٹ فریم ورک) کے ساتھ چائی (ایک دعویٰ لائبریری) کا استعمال کرتے ہیں۔ آپ کو بس `npx hardhat test` چلانا ہے اور درج ذیل پیغام کے ظاہر ہونے کا انتظار کرنا ہے۔ - -```bash -✓ Should return the new greeting once it's changed -``` - -### اب تک سب کچھ بہت اچھا لگ رہا ہے، آئیے اپنے پروجیکٹ میں کچھ اور پیچیدگی شامل کریں {#adding-complexity} - -ایسی صورتحال کا تصور کریں جہاں کوئی شخص بطور گریٹنگ ایک خالی سٹرنگ شامل کرتا ہے۔ یہ ایک پرجوش گریٹنگ نہیں ہوگی، ہے نا؟ -آئیے اس بات کو یقینی بنائیں کہ ایسا نہ ہو: - -جب کوئی خالی سٹرنگ پاس کرتا ہے تو ہم سولڈیٹی کے `revert` کا استعمال کرنا چاہتے ہیں۔ اچھی بات یہ ہے کہ ہم اس فنکشنلٹی کو وافل کے چائی میچر `to.be.revertedWith()` کے ساتھ آسانی سے ٹیسٹ کر سکتے ہیں۔ - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -ایسا لگتا ہے کہ ہمارا نیا ٹیسٹ پاس نہیں ہوا: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -آئیے اس فنکشنلٹی کو اپنے اسمارٹ کنٹریکٹ میں نافذ کریں: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -اب، ہمارا setGreeting فنکشن اس طرح لگتا ہے: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -آئیے دوبارہ ٹیسٹ چلائیں: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -مبارک ہو! آپ نے کر دکھایا :) - -### نتیجہ {#conclusion} - -ہم نے وافل، ہارڈ ہیٹ اور ethers.js کے ساتھ ایک سادہ پروجیکٹ بنایا۔ ہم نے ایک پروجیکٹ سیٹ اپ کرنے، ایک ٹیسٹ شامل کرنے اور نئی فنکشنلٹی کو نافذ کرنے کا طریقہ سیکھا۔ - -اپنے اسمارٹ کنٹریکٹس کی جانچ کے لیے مزید بہترین چائی میچرز کے لیے، [آفیشل وافل کے دستاویزات](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html) دیکھیں۔ diff --git a/public/content/translations/ur/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/ur/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 7582a670e40..00000000000 --- a/public/content/translations/ur/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "Waffle لائبریری کے ساتھ سادہ اسمارٹ کنٹریکٹ کی جانچ" -description: "ابتدائی افراد کے لیے ٹیوٹوریل" -author: Ewa Kowalska -tags: [ "اسمارٹ معاہدات", "solidity", "Waffle", "testing" ] -skill: beginner -lang: ur-in -published: 2021-02-26 ---- - -## اس ٹیوٹوریل میں آپ سیکھیں گے کہ کیسے {#in-this-tutorial-youll-learn-how-to} - -- والیٹ بیلنس کی تبدیلیوں کی جانچ کریں -- مخصوص دلائل کے ساتھ ایونٹس کے اخراج کی جانچ کریں -- اس بات کی تصدیق کریں کہ ٹرانزیکشن کو واپس کر دیا گیا تھا - -## مفروضات {#assumptions} - -- آپ ایک نیا JavaScript یا TypeScript پروجیکٹ بنا سکتے ہیں -- آپ کو JavaScript میں ٹیسٹ کا کچھ بنیادی تجربہ ہے -- آپ نے کچھ پیکیج مینیجرز جیسے yarn یا npm کا استعمال کیا ہے -- آپ کو اسمارٹ کنٹریکٹس اور Solidity کا بہت بنیادی علم ہے - -## شروعات کرنا {#getting-started} - -یہ ٹیوٹوریل yarn کا استعمال کرتے ہوئے ٹیسٹ سیٹ اپ اور رن کا مظاہرہ کرتا ہے، لیکن اگر آپ npm کو ترجیح دیتے ہیں تو کوئی مسئلہ نہیں ہے - میں سرکاری Waffle [ڈاکیومینٹیشن](https://ethereum-waffle.readthedocs.io/en/latest/index.html) کے مناسب حوالے فراہم کروں گا۔ - -## ڈیپینڈینسیز انسٹال کریں {#install-dependencies} - -اپنے پروجیکٹ کی ڈیو ڈیپینڈینسیز میں ethereum-waffle اور typescript ڈیپینڈینسیز کو [شامل کریں](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)۔ - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## مثالی اسمارٹ کنٹریکٹ {#example-smart-contract} - -ٹیوٹوریل کے دوران ہم ایک سادہ اسمارٹ کنٹریکٹ کی مثال - EtherSplitter پر کام کریں گے۔ یہ کسی کو کچھ wei بھیجنے اور اسے دو پہلے سے طے شدہ ریسیورز کے درمیان برابر تقسیم کرنے کی اجازت دینے کے علاوہ زیادہ کچھ نہیں کرتا ہے۔ -اسپلٹ فنکشن کے لیے wei کی تعداد کا جفت ہونا ضروری ہے، ورنہ یہ واپس ہو جائے گا۔ دونوں ریسیورز کے لیے یہ ایک wei ٹرانسفر کرتا ہے جس کے بعد Transfer ایونٹ کا اخراج ہوتا ہے۔ - -EtherSplitter کوڈ کے اسنیپٹ کو `src/EtherSplitter.sol` میں رکھیں۔ - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## کنٹریکٹ کو کمپائل کریں {#compile-the-contract} - -کنٹریکٹ کو [کمپائل](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) کرنے کے لیے، package.json فائل میں درج ذیل اندراج شامل کریں: - -```json -"scripts": { - "build": "waffle" - } -``` - -اگلا، پروجیکٹ روٹ ڈائرکٹری میں Waffle کنفیگریشن فائل - `waffle.json` - بنائیں اور پھر وہاں درج ذیل کنفیگریشن پیسٹ کریں: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -`yarn build` چلائیں۔ نتیجے کے طور پر، `build` ڈائرکٹری JSON فارمیٹ میں EtherSplitter کمپائلڈ کنٹریکٹ کے ساتھ ظاہر ہوگی۔ - -## ٹیسٹ سیٹ اپ {#test-setup} - -Waffle کے ساتھ ٹیسٹنگ کے لیے Chai matchers اور Mocha کا استعمال ضروری ہے، لہذا آپ کو انہیں اپنے پروجیکٹ میں [شامل](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) کرنے کی ضرورت ہے۔ اپنی package.json فائل کو اپ ڈیٹ کریں اور اسکرپٹس حصے میں `test` اندراج شامل کریں: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -اگر آپ اپنے ٹیسٹ [ایگزیکیوٹ](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests) کرنا چاہتے ہیں تو صرف `yarn test` چلائیں۔ - -## جانچ {#testing} - -اب `test` ڈائرکٹری بنائیں اور نئی فائل `test\EtherSplitter.test.ts` بنائیں۔ -نیچے دیے گئے اسنیپٹ کو کاپی کریں اور اسے ہماری ٹیسٹ فائل میں پیسٹ کریں۔ - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // add the tests here -}) -``` - -شروع کرنے سے پہلے چند باتیں۔ -`MockProvider` بلاک چین کا ایک موک ورژن فراہم کرتا ہے۔ یہ موک والیٹس بھی فراہم کرتا ہے جو EtherSplitter کنٹریکٹ کی جانچ کے لیے ہماری خدمت کریں گے۔ ہم پرووائڈر پر `getWallets()` میتھڈ کو کال کرکے دس والیٹس تک حاصل کرسکتے ہیں۔ مثال میں، ہم تین والیٹس حاصل کرتے ہیں - بھیجنے والے (sender) کے لیے اور دو وصول کنندگان (receivers) کے لیے۔ - -اگلا، ہم 'splitter' نامی ایک متغیر کا اعلان کرتے ہیں - یہ ہمارا موک EtherSplitter کنٹریکٹ ہے۔ یہ `deployContract` میتھڈ کے ذریعہ ہر ایک ٹیسٹ کے ایگزیکیوشن سے پہلے بنایا جاتا ہے۔ یہ میتھڈ پہلے پیرامیٹر کے طور پر پاس کیے گئے والیٹ (ہمارے معاملے میں بھیجنے والے کا والیٹ) سے ایک کنٹریکٹ کی تعیناتی کی نقل کرتا ہے۔ دوسرا پیرامیٹر ٹیسٹ شدہ کنٹریکٹ کا ABI اور بائٹ کوڈ ہے - ہم وہاں `build` ڈائرکٹری سے کمپائل شدہ EtherSplitter کنٹریکٹ کی json فائل پاس کرتے ہیں۔ تیسرا پیرامیٹر کنٹریکٹ کے کنسٹرکٹر دلائل کے ساتھ ایک ارے ہے، جو ہمارے معاملے میں، دو وصول کنندگان کے ایڈریس ہیں۔ - -## changeBalances {#changebalances} - -سب سے پہلے، ہم یہ چیک کریں گے کہ آیا اسپلٹ میتھڈ واقعی وصول کنندگان کے والیٹس کے بیلنس کو تبدیل کرتا ہے۔ اگر ہم بھیجنے والے کے اکاؤنٹ سے 50 wei کو اسپلٹ کرتے ہیں، تو ہم توقع کریں گے کہ دونوں وصول کنندگان کے بیلنس میں 25 wei کا اضافہ ہوگا۔ ہم Waffle کا `changeBalances` میچر استعمال کریں گے: - -```ts -it("Changes accounts balances", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -میچر کے پہلے پیرامیٹر کے طور پر، ہم وصول کنندگان کے والیٹس کا ایک ارے پاس کرتے ہیں، اور دوسرے کے طور پر - متعلقہ اکاؤنٹس پر متوقع اضافے کا ایک ارے۔ -اگر ہم کسی ایک مخصوص والیٹ کا بیلنس چیک کرنا چاہتے ہیں، تو ہم `changeBalance` میچر بھی استعمال کر سکتے ہیں، جس کے لیے ارے پاس کرنے کی ضرورت نہیں ہے، جیسا کہ نیچے دی گئی مثال میں ہے: - -```ts -it("Changes account balance", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -نوٹ کریں کہ `changeBalance` اور `changeBalances` دونوں صورتوں میں ہم اسپلٹ فنکشن کو کال بیک کے طور پر پاس کرتے ہیں کیونکہ میچر کو کال سے پہلے اور بعد میں بیلنس کی حالت تک رسائی کی ضرورت ہوتی ہے۔ - -اگلا، ہم جانچیں گے کہ کیا Transfer ایونٹ ہر wei کی منتقلی کے بعد خارج ہوا تھا۔ ہم Waffle سے ایک اور میچر کی طرف رجوع کریں گے: - -## Emit {#emit} - -```ts -it("Emits event on the transfer to the first receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("Emits event on the transfer to the second receiver", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit` میچر ہمیں یہ چیک کرنے کی اجازت دیتا ہے کہ آیا کسی کنٹریکٹ نے میتھڈ کال کرنے پر کوئی ایونٹ خارج کیا ہے۔ `emit` میچر کے پیرامیٹرز کے طور پر، ہم وہ موک کنٹریکٹ فراہم کرتے ہیں جس کے بارے میں ہم پیش گوئی کرتے ہیں کہ وہ ایونٹ خارج کرے گا، اس ایونٹ کے نام کے ساتھ۔ ہمارے معاملے میں، موک کنٹریکٹ `splitter` ہے اور ایونٹ کا نام - `Transfer` ہے۔ ہم ان دلائل کی درست قدروں کی بھی تصدیق کر سکتے ہیں جن کے ساتھ ایونٹ خارج کیا گیا تھا - ہم `withArgs` میچر کو اتنے ہی دلائل پاس کرتے ہیں، جتنے ہمارے ایونٹ کے اعلان کی توقع ہے۔ EtherSplitter کنٹریکٹ کے معاملے میں، ہم بھیجنے والے اور وصول کنندہ کے ایڈریس کے ساتھ منتقل شدہ wei رقم کو پاس کرتے ہیں۔ - -## revertedWith {#revertedwith} - -آخری مثال کے طور پر، ہم یہ چیک کریں گے کہ آیا wei کی غیر مساوی تعداد کی صورت میں ٹرانزیکشن کو واپس کر دیا گیا تھا۔ ہم `revertedWith` میچر استعمال کریں گے: - -```ts -it("Reverts when Vei amount uneven", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -یہ ٹیسٹ، اگر پاس ہو جاتا ہے، تو ہمیں یقین دلائے گا کہ ٹرانزیکشن واقعی واپس کر دی گئی تھی۔ تاہم، `require` اسٹیٹمنٹ میں ہمارے پاس کیے گئے پیغامات اور `revertedWith` میں ہماری توقع کے پیغام کے درمیان ایک عین مطابق مماثلت بھی ہونی چاہیے۔ اگر ہم EtherSplitter کنٹریکٹ کے کوڈ پر واپس جائیں، تو wei رقم کے لیے `require` اسٹیٹمنٹ میں، ہم یہ پیغام فراہم کرتے ہیں: 'Uneven wei amount not allowed'۔ یہ اس پیغام سے میل کھاتا ہے جس کی ہم اپنے ٹیسٹ میں توقع کرتے ہیں۔ اگر وہ برابر نہ ہوتے تو ٹیسٹ فیل ہو جاتا۔ - -## مبارک ہو! {#congratulations} - -آپ نے Waffle کے ساتھ اسمارٹ کنٹریکٹس کی جانچ کی طرف اپنا پہلا بڑا قدم اٹھایا ہے! diff --git a/public/content/translations/zh-tw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/zh-tw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 3c0f4e7b76f..00000000000 --- a/public/content/translations/zh-tw/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle:動態模擬與測試合約呼叫" -description: "使用動態模擬與測試合約呼叫的進階 Waffle 教學" -author: "Daniel Izdebski" -tags: [ "waffle", "smart contracts", "solidity", "testing", "mocking" ] -skill: intermediate -lang: zh-tw -published: 2020-11-14 ---- - -## 本教學的主題是什麼? {#what-is-this-tutorial-about} - -在本教學中,您將學習如何: - -- 使用動態模擬 -- 測試智能合約之間的互動 - -假設: - -- 您已經知道如何用 `Solidity` 編寫簡單的智能合約 -- 您熟悉 `JavaScript` 和 `TypeScript` -- 您已經完成其他 `Waffle` 教學,或對它略知一二 - -## 動態模擬 {#dynamic-mocking} - -為什麼動態模擬很有用? 嗯,它讓我們可以編寫單元測試,而不是整合測試。 這是什麼意思呢? 這表示我們不必擔心智能合約的依賴性,因此我們可以在完全隔離的環境中測試所有合約。 讓我為您示範確切的做法。 - -### **1. 專案** {#1-project} - -在開始之前,我們需要準備一個簡單的 node.js 專案: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# 或者如果您使用 npm -npm init -``` - -讓我們先加入 typescript 和測試依賴項 - mocha 和 chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# 或者如果您使用 npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -現在,讓我們加入 `Waffle` 和 `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# 或者如果您使用 npm -npm install ethereum-waffle ethers --save-dev -``` - -您的專案結構現在應該如下所示: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. 智能合約** {#2-smart-contract} - -要開始動態模擬,我們需要一個有依賴項的智能合約。 別擔心,我已經為您準備好了! - -這是一個用 `Solidity` 編寫的簡單智能合約,其唯一目的是檢查我們是否富有。 它使用 ERC20 代幣來檢查我們是否有足夠的代幣。 將它放在 `./contracts/AmIRichAlready.sol` 中。 - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -因為我們要使用動態模擬,所以我們不需要完整的 ERC20,這就是為什麼我們只使用具有單一函數的 IERC20 介面。 - -是時候建置這個合約了! 為此,我們將使用 `Waffle`。 首先,我們要建立一個簡單的 `waffle.json` 設定檔,用來指定編譯選項。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -現在我們準備好用 Waffle 來建置合約了: - -```bash -npx waffle -``` - -很簡單,對吧? 在 `build/` 資料夾中,會出現兩個分別對應合約和介面的檔案。 我們稍後會用它們來進行測試。 - -### **3. 測試** {#3-testing} - -讓我們建立一個名為 `AmIRichAlready.test.ts` 的檔案,用於實際測試。 首先,我們必須處理匯入的部分。 我們稍後會需要它們: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -除了 JS 依賴項之外,我們還需要匯入建置好的合約和介面: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle 使用 `chai` 進行測試。 不過,在使用之前,我們必須將 Waffle 的匹配器注入 chai 本身: - -```typescript -use(solidity) -``` - -我們需要實作 `beforeEach()` 函數,它會在每次測試前重設合約的狀態。 讓我們先想一下我們需要什麼。 要部署合約,我們需要兩樣東西:一個錢包,以及一個已部署的 ERC20 合約,以便將它作為引數傳遞給 `AmIRichAlready` 合約。 - -首先,我們建立一個錢包: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -然後,我們需要部署一個 ERC20 合約。 棘手的部分來了——我們只有一個介面。 這就是 Waffle 派上用場的時候了。 Waffle 有一個神奇的 `deployMockContract()` 函數,它只用介面的 _abi_ 就能建立一個合約: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -現在有了錢包和已部署的 ERC20,我們就可以繼續部署 `AmIRichAlready` 合約了: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -這樣一來,我們的 `beforeEach()` 函數就完成了。 到目前為止,您的 `AmIRichAlready.test.ts` 檔案應該如下所示: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("我已經富有了嗎", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -讓我們為 `AmIRichAlready` 合約編寫第一個測試。 您認為我們的測試應該關於什麼? 是的,您說對了! 我們應該檢查我們是否已經富有了 :) - -但請等一下。 我們的模擬合約要如何知道該傳回什麼值? 我們還沒有為 `balanceOf()` 函數實作任何邏輯。 同樣地,Waffle 在這裡可以幫上忙。 我們的模擬合約現在有了一些酷炫的新功能: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -有了這些知識,我們終於可以編寫我們的第一個測試了: - -```typescript -it("如果錢包的代幣少於 1,000,000,則傳回 false", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -讓我們把這個測試分解成幾個部分: - -1. 我們將模擬 ERC20 合約設定為一律傳回 999,999 枚代幣的餘額。 -2. 檢查 `contract.check()` 方法是否傳回 `false`。 - -我們準備好來啟動這個大傢伙了: - -![一個測試通過](./test-one.png) - -所以測試成功了,但是…… 還有一些改進的空間。 `balanceOf()` 函數將一律傳回 99999。 我們可以透過指定函數應為哪個錢包傳回某些內容來改進它——就像一個真正的合約一樣: - -```typescript -it("如果錢包的代幣少於 1,000,001,則傳回 false", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -到目前為止,我們只測試了我們不夠富有的情況。 讓我們來測試相反的情況: - -```typescript -it("如果錢包至少有 1,000,001 個代幣,則傳回 true", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -您執行測試…… - -![兩個測試通過](test-two.png) - -……然後就完成了! 我們的合約似乎如預期般運作 :) - -## 測試合約呼叫 {#testing-contract-calls} - -讓我們總結一下目前為止所做的事情。 我們已經測試了 `AmIRichAlready` 合約的功能,它似乎運作正常。 這表示我們完成了,對吧? 不完全是! Waffle 讓我們可以更進一步地測試合約。 但確切要怎麼做呢? 嗯,在 Waffle 的工具箱裡,有 `calledOnContract()` 和 `calledOnContractWith()` 匹配器。 它們讓我們可以檢查我們的合約是否呼叫了 ERC20 模擬合約。 以下是使用其中一個匹配器的基本測試: - -```typescript -it("檢查合約是否在 ERC20 代幣上呼叫了 balanceOf", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -我們可以更進一步,用我跟您提過的另一個匹配器來改進這個測試: - -```typescript -it("檢查合約是否在 ERC20 代幣上用特定錢包呼叫了 balanceOf", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -讓我們檢查測試是否正確: - -![三個測試通過](test-three.png) - -太好了,所有測試都顯示為綠色。 - -用 Waffle 測試合約呼叫非常簡單。 最棒的是。 這些匹配器對一般合約和模擬合約都有效! 這是因為 Waffle 記錄並過濾 EVM 呼叫,而不是像其他技術的流行測試函式庫那樣注入程式碼。 - -## 終點線 {#the-finish-line} - -恭喜! 現在您知道如何使用 Waffle 來測試合約呼叫和動態模擬合約了。 還有更多有趣的功能等著您去發掘。 我建議您深入研究 Waffle 的文件。 - -Waffle 的文件可從[此處](https://ethereum-waffle.readthedocs.io/)取得。 - -本教學的原始程式碼可以在[這裡](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls)找到。 - -您可能也會感興趣的教學: - -- [用 Waffle 測試智能合約](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/zh-tw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/zh-tw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 1ad4249c95f..00000000000 --- a/public/content/translations/zh-tw/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "使用 hardhat 和 ethers 的 Waffle hello world 教學" -description: "使用 hardhat 和 ethers.js 建立您的第一個 Waffle 專案" -author: "MiZiet" -tags: - [ - "waffle", - "smart contracts", - "solidity", - "testing", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: zh-tw -published: 2020-10-16 ---- - -在本 [Waffle](https://ethereum-waffle.readthedocs.io) 教學中,我們將學習如何使用 [hardhat](https://hardhat.org/) 和 [ethers.js](https://docs.ethers.io/v5/) 設定一個簡單的「Hello world」智能合約專案。 然後,我們將學習如何為我們的智能合約新增功能,以及如何用 Waffle 進行測試。 - -讓我們從建立一個新專案開始: - -```bash -yarn init -``` - -或 - -```bash -npm init -``` - -並安裝必要的套件: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -或 - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -下一步是執行 `npx hardhat` 來建立一個範例 hardhat 專案。 - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 Welcome to Hardhat v2.0.3 👷‍ - -? What do you want to do? … -❯ Create a sample project -Create an empty hardhat.config.js -Quit -``` - -選擇 `Create a sample project` - -我們專案的結構應該如下所示: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### 現在讓我們來談談其中一些檔案: {#now-lets-talk} - -- Greeter.sol - 我們用 solidity 編寫的智能合約; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("正在部署帶有問候語的 Greeter:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("正在將問候語從「%s」變更為「%s」", greeting, _greeting); -greeting = _greeting; -} -} -``` - -我們的智能合約可以分為三個部分: - -1. constructor - 我們在這裡宣告一個名為 `greeting` 的字串類型變數, -2. function greet - 一個在被呼叫時會回傳 `greeting` 的函式, -3. function setGreeting - 一個讓我們可以變更 `greeting` 值的函式。 - -- sample-test.js - 我們的測試檔案 - -```js -describe("Greeter", function () { - it("變更後應回傳新的問候語", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### 下一步是編譯我們的合約並執行測試: {#compiling-and-testing} - -Waffle 測試使用 Mocha (一個測試框架) 和 Chai (一個斷言庫)。 您只需執行 `npx hardhat test`,並等待以下訊息出現即可。 - -```bash -✓ 變更後應回傳新的問候語 -``` - -### 目前為止一切看起來都很好,讓我們為專案增加一點複雜性吧 {#adding-complexity} - -想像一下,有人將一個空字串作為問候語新增進來。 那不會是個熱情的問候,對吧? -讓我們確保這種情況不會發生: - -當有人傳入空字串時,我們希望使用 solidity 的 `revert`。 好消息是,我們可以用 Waffle 的 chai 匹配器 `to.be.revertedWith()` 輕鬆地測試此功能。 - -```js -it("傳入空字串時應還原", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "問候語不應為空" - ) -}) -``` - -看來我們的新測試沒有通過: - -```bash -正在部署帶有問候語的 Greeter:Hello, world! -正在將問候語從 'Hello, world!' 變更為 'Hola, mundo!' - ✓ 變更後應回傳新的問候語 (1514ms) -正在部署帶有問候語的 Greeter:Hello, world! -正在將問候語從 'Hello, world!' 變更為 '' - 1) 傳入空字串時應還原 - - - 1 個通過 (2s) - 1 個失敗 -``` - -讓我們在智能合約中實作此功能: - -```solidity -require(bytes(_greeting).length > 0, "問候語不應為空"); -``` - -現在,我們的 setGreeting 函式看起來像這樣: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "問候語不應為空"); -console.log("正在將問候語從「%s」變更為「%s」", greeting, _greeting); -greeting = _greeting; -} -``` - -讓我們再執行一次測試: - -```bash -✓ 變更後應回傳新的問候語 (1467ms) -✓ 傳入空字串時應還原 (276ms) - -2 個通過 (2s) -``` - -恭喜! 您做到了 :) - -### 結論 {#conclusion} - -我們用 Waffle、Hardhat 和 ethers.js 建立了一個簡單的專案。 我們學會了如何設定專案、新增測試和實作新功能。 - -想了解更多用於測試智能合約的強大 chai 匹配器,請查看 [Waffle 的官方文件](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)。 diff --git a/public/content/translations/zh-tw/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/zh-tw/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 250c785ca85..00000000000 --- a/public/content/translations/zh-tw/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "使用 Waffle 程式庫測試簡單的智能合約" -description: "初學者教學" -author: Ewa Kowalska -tags: [ "smart contracts", "solidity", "Waffle", "testing" ] -skill: beginner -lang: zh-tw -published: 2021-02-26 ---- - -## 在本教學中,你將學會如何 {#in-this-tutorial-youll-learn-how-to} - -- 測試錢包餘額的變動 -- 使用指定的引數測試事件發出 -- 斷言交易已被回復 - -## 假設 {#assumptions} - -- 你可以建立一個新的 JavaScript 或 TypeScript 專案 -- 你擁有基本的 JavaScript 測試經驗 -- 你使用過一些套件管理器,例如 yarn 或 npm -- 你擁有智能合約和 Solidity 的基本知識 - -## 入門 {#getting-started} - -本教學示範如何使用 yarn 設定和執行測試,但如果你偏好使用 npm 也沒有問題——我會提供 Waffle 官方[文件](https://ethereum-waffle.readthedocs.io/en/latest/index.html)的相應參考資料。 - -## 安裝相依性 {#install-dependencies} - -將 ethereum-waffle 和 typescript 相依性[新增](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)到你專案的開發相依性中。 - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## 智能合約範例 {#example-smart-contract} - -在本教學中,我們將使用一個簡單的智能合約範例——EtherSplitter。 它的功能不多,只不過是讓任何人都能傳送一些 wei,並將其平均分配給兩個預先定義的接收者。 -split 函式要求 wei 的數量必須是偶數,否則交易將會回復。 對於兩個接收者,它都會執行一筆 wei 轉帳,然後發出 Transfer 事件。 - -將 EtherSplitter 的程式碼片段放在 `src/EtherSplitter.sol` 中。 - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, '不允許奇數的 wei 金額'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## 編譯合約 {#compile-the-contract} - -若要[編譯](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)合約,請將以下項目新增至 package.json 檔案中: - -```json -"scripts": { - "build": "waffle" - } -``` - -接著,在專案的根目錄中建立 Waffle 設定檔——`waffle.json`——然後在其中貼上以下設定: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -執行 `yarn build`。 結果 `build` 目錄將會出現,其中包含 JSON 格式的已編譯 EtherSplitter 合約。 - -## 測試設定 {#test-setup} - -使用 Waffle 進行測試需要使用 Chai 比對器和 Mocha,因此你需要將它們[新增](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)到你的專案中。 更新你的 package.json 檔案,並在 scripts 部分新增 `test` 項目: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -如果你想[執行](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests)你的測試,只要執行 `yarn test` 即可。 - -## 測試 {#testing} - -現在建立 `test` 目錄,並建立新檔案 `test\EtherSplitter.test.ts`。 -複製下方的程式碼片段並貼到我們的測試檔案中。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether 分配器", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // 在此處新增測試 -}) -``` - -在我們開始之前,先說幾句話。 -`MockProvider` 提供一個模擬版本的區塊鏈。 它也提供模擬錢包,我們將用它來測試 EtherSplitter 合約。 我們可以透過在提供者上呼叫 `getWallets()` 方法來取得最多十個錢包。 在這個範例中,我們取得三個錢包——一個給傳送者,兩個給接收者。 - -接著,我們宣告一個名為「splitter」的變數——這是我們的模擬 EtherSplitter 合約。 它會在每次執行單一測試前,由 `deployContract` 方法建立。 此方法會模擬從作為第一個參數傳入的錢包(在我們的案例中是傳送者的錢包)部署合約。 第二個參數是被測試合約的 ABI 和位元組碼——我們在此傳入 `build` 目錄中已編譯的 EtherSplitter 合約的 json 檔案。 第三個參數是一個包含合約建構函式引數的陣列,在我們的案例中,是兩個接收者的地址。 - -## changeBalances {#changebalances} - -首先,我們將檢查 split 方法是否真的會改變接收者錢包的餘額。 如果我們從傳送者帳戶中分出 50 wei,我們預期兩個接收者的餘額都會增加 25 wei。 我們將使用 Waffle 的 `changeBalances` 比對器: - -```ts -it("改變帳戶餘額", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -我們將接收者錢包的陣列作為比對器的第一個參數傳入,並將對應帳戶的預期增額陣列作為第二個參數傳入。 -如果我們想檢查某個特定錢包的餘額,我們也可以使用 `changeBalance` 比對器,它不需要傳入陣列,如下方範例所示: - -```ts -it("改變帳戶餘額", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -請注意,在 `changeBalance` 和 `changeBalances` 的情況下,我們都將 split 函式作為回呼傳遞,因為比對器需要在呼叫前後存取餘額的狀態。 - -接下來,我們將測試每次轉移 wei 後是否發出了 Transfer 事件。 我們將使用 Waffle 的另一個比對器: - -## Emit {#emit} - -```ts -it("向第一個接收者轉帳時發出事件", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("向第二個接收者轉帳時發出事件", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit` 比對器讓我們可以檢查合約在呼叫方法時是否發出了事件。 我們將預測會發出事件的模擬合約以及該事件的名稱,作為 `emit` 比對器的參數。 在我們的案例中,模擬合約是 `splitter`,事件名稱是 `Transfer`。 我們也可以驗證事件發出時所帶引數的確切值——我們傳遞給 `withArgs` 比對器的引數數量,與我們的事件宣告所預期的數量相同。 在 EtherSplitter 合約的案例中,我們傳入傳送者和接收者的地址以及轉帳的 wei 金額。 - -## revertedWith {#revertedwith} - -作為最後一個範例,我們將檢查在 wei 數量為奇數的情況下,交易是否被回復。 我們將使用 `revertedWith` 比對器: - -```ts -it("當 wei 金額為奇數時回復", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "不允許奇數的 wei 金額" - ) -}) -``` - -如果測試通過,將確保交易確實已被回復。 但是,我們在 `require` 陳述式中傳遞的訊息,必須與我們在 `revertedWith` 中預期的訊息完全相符。 如果我們回到 EtherSplitter 合約的程式碼,在針對 wei 金額的 `require` 陳述式中,我們提供的訊息是:「不允許奇數的 wei 金額」。 這與我們在測試中預期的訊息相符。 如果兩者不相等,測試就會失敗。 - -## 恭喜! {#congratulations} - -你已經邁出了使用 Waffle 測試智能合約的第一大步! diff --git a/public/content/translations/zh/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md b/public/content/translations/zh/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md deleted file mode 100644 index d43426a5445..00000000000 --- a/public/content/translations/zh/developers/tutorials/testing-erc-20-tokens-with-waffle/index.md +++ /dev/null @@ -1,1145 +0,0 @@ ---- -title: 使用 Waffle 测试 ERC-20 代币 -description: 学习如何测试 Solidity 智能合约,以及如何将智能合约匹配器与 Waffle 配合使用 -author: Vladislav Starostenko -tags: - - "waffle" - - "智能合约" - - "solidity" - - "测试" - - "erc-20" -skill: intermediate -lang: zh -published: 2020-10-16 ---- - -在本教程中,你将学习如何: - -- 使用 Waffle 编写智能合约测试 -- 使用一些流行的匹配器,配合 Waffle 来测试智能合约 - -本文假定: - -- 你熟悉终端操作, -- 你能够创建一个新的 `JavaScript` 项目, -- 你写过一些 `Solidity` 代码, -- 你使用 `JavaScript` 写过一些测试, -- 你使用过 JavaScripts 的包安装程序,`yarn` 或 `npm`。 - -再次强调,如果你不符合其中任何一条,或者你不打算敲本文中的代码,你照着学仍然可以学得很好。 - -## 关于 Waffle 的几句话 {#a-few-words-about-waffle} - -[Waffle](https://getwaffle.io) 是用于编写和测试智能合约的最先进的库。 - -使用 [JavaScript API](/developers/docs/apis/javascript/) ethers-js。 - -你可以在 [Waffle 文档](https://ethereum-waffle.readthedocs.io/en/latest/#waffle-documentation)中阅读更多详细信息! - -## 快速教程 {#the-quick-tutorial} - -首先,创建新的 `JavaScript` 或 `TypeScript` 项目(我将使用 `TS`,但如果你使用 `JS`,问题也不大 ): - -有点像这样: - -
-package.json - -```json - { - "name": "tutorial", - "version": "1.0.0", - "main": "index.js", - "license": "MIT", - "scripts": { - "test": "export NODE_ENV=test && mocha", - "lint": "eslint '{src,test}/**/*.ts'", - "lint:fix": "eslint --fix '{src,test}/**/*.ts'", - "build": "waffle" - }, - "devDependencies": { - "@types/mocha": "^5.2.7", - "@typescript-eslint/eslint-plugin": "^2.30.0", - "@typescript-eslint/parser": "^2.30.0", - "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.2", - "ethers": "^5.0.17", - "mocha": "^7.1.2", - "ts-node": "^8.9.1", - "typescript": "^3.8.3" - } - } -``` - -
- -
-tsconfig.json - -```json - { - "compilerOptions": { - "declaration": true, - "esModuleInterop": true, - "lib": [ - "ES2018" - ], - "module": "CommonJS", - "moduleResolution": "node", - "outDir": "dist", - "resolveJsonModule": true, - "skipLibCheck": true, - "strict": true, - "target": "ES2018" - } - } -``` - -
- -
-.gitignore - - node_modules - build - -
- -
-.eslintrc.js - -```js - module.exports = { - "env": { - "es6": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:import/typescript" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "error", - { - "accessibility": "no-public", - "overrides": { - "parameterProperties": "off" - } - } - ], - "@typescript-eslint/indent": [ - "error", - 2, - { - "ArrayExpression": 1, - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 1 - }, - "FunctionExpression": { - "body": 1, - "parameters": 1 - }, - "ImportDeclaration": 1, - "MemberExpression": 1, - "ObjectExpression": 1, - "SwitchCase": 1, - "VariableDeclarator": 1, - "flatTernaryExpressions": false, - "ignoreComments": false, - "outerIIFEBody": 1 - } - ], - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": [ - "error", - { - "multiline": { - "delimiter": "semi", - "requireLast": true - }, - "singleline": { - "delimiter": "semi", - "requireLast": false - } - } - ], - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "ignoreRestSiblings": true, - "vars": "all" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-useless-constructor": "error", - "@typescript-eslint/no-var-requires": "warn", - "accessor-pairs": "error", - "array-bracket-spacing": [ - "error", - "never" - ], - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "block-spacing": [ - "error", - "always" - ], - "brace-style": [ - "error", - "1tbs", - { - "allowSingleLine": true - } - ], - "camelcase": "off", - "comma-dangle": [ - "error", - { - "arrays": "never", - "exports": "never", - "functions": "never", - "imports": "never", - "objects": "never" - } - ], - "comma-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "comma-style": [ - "error", - "last" - ], - "computed-property-spacing": [ - "error", - "never" - ], - "constructor-super": "error", - "curly": [ - "error", - "multi-line" - ], - "dot-location": [ - "error", - "property" - ], - "eol-last": "error", - "eqeqeq": [ - "error", - "always", - { - "null": "ignore" - } - ], - "func-call-spacing": [ - "error", - "never" - ], - "generator-star-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "handle-callback-err": [ - "error", - "^(err|error)$" - ], - "import/default": "off", - "import/named": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": false - } - ], - "import/no-unresolved": "off", - "indent": "off", - "key-spacing": [ - "error", - { - "afterColon": true, - "beforeColon": false - } - ], - "keyword-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "lines-between-class-members": [ - "error", - "always", - { - "exceptAfterSingleLine": true - } - ], - "max-len": [ - "error", - { - "code": 120 - } - ], - "new-cap": [ - "error", - { - "capIsNew": false, - "newIsCap": true - } - ], - "new-parens": "error", - "no-array-constructor": "error", - "no-async-promise-executor": "error", - "no-caller": "error", - "no-class-assign": "error", - "no-compare-neg-zero": "error", - "no-cond-assign": "error", - "no-const-assign": "error", - "no-constant-condition": [ - "error", - { - "checkLoops": false - } - ], - "no-control-regex": "error", - "no-debugger": "error", - "no-delete-var": "error", - "no-dupe-args": "error", - "no-dupe-keys": "error", - "no-duplicate-case": "error", - "no-empty-character-class": "error", - "no-empty-pattern": "error", - "no-eval": "error", - "no-ex-assign": "error", - "no-extend-native": "error", - "no-extra-bind": "error", - "no-extra-boolean-cast": "error", - "no-extra-parens": [ - "error", - "functions" - ], - "no-fallthrough": "error", - "no-floating-decimal": "error", - "no-func-assign": "error", - "no-global-assign": "error", - "no-implied-eval": "error", - "no-inner-declarations": [ - "error", - "functions" - ], - "no-invalid-regexp": "error", - "no-irregular-whitespace": "error", - "no-iterator": "error", - "no-label-var": "error", - "no-labels": [ - "error", - { - "allowLoop": false, - "allowSwitch": false - } - ], - "no-lone-blocks": "error", - "no-misleading-character-class": "error", - "no-mixed-operators": [ - "error", - { - "allowSamePrecedence": true, - "groups": [ - [ - "==", - "!=", - "===", - "!==", - ">", - ">=", - "<", - "<=" - ], - [ - "&&", - "||" - ], - [ - "in", - "instanceof" - ] - ] - } - ], - "no-mixed-spaces-and-tabs": "error", - "no-multi-spaces": "error", - "no-multi-str": "error", - "no-multiple-empty-lines": [ - "error", - { - "max": 1, - "maxEOF": 0 - } - ], - "no-negated-in-lhs": "error", - "no-new": "error", - "no-new-func": "error", - "no-new-object": "error", - "no-new-require": "error", - "no-new-symbol": "error", - "no-new-wrappers": "error", - "no-obj-calls": "error", - "no-octal": "error", - "no-octal-escape": "error", - "no-path-concat": "error", - "no-proto": "error", - "no-prototype-builtins": "error", - "no-redeclare": [ - "error", - { - "builtinGlobals": false - } - ], - "no-regex-spaces": "error", - "no-return-assign": [ - "error", - "except-parens" - ], - "no-return-await": "error", - "no-self-assign": "error", - "no-self-compare": "error", - "no-sequences": "error", - "no-shadow-restricted-names": "error", - "no-sparse-arrays": "error", - "no-tabs": "error", - "no-template-curly-in-string": "error", - "no-this-before-super": "error", - "no-throw-literal": "error", - "no-trailing-spaces": "error", - "no-unexpected-multiline": "error", - "no-unmodified-loop-condition": "error", - "no-unneeded-ternary": [ - "error", - { - "defaultAssignment": false - } - ], - "no-unreachable": "error", - "no-unsafe-finally": "error", - "no-unsafe-negation": "error", - "no-use-before-define": [ - "error", - { - "classes": false, - "functions": false, - "variables": false - } - ], - "no-useless-call": "error", - "no-useless-catch": "error", - "no-useless-computed-key": "error", - "no-useless-escape": "error", - "no-useless-rename": "error", - "no-useless-return": "error", - "no-whitespace-before-property": "error", - "no-with": "error", - "object-curly-spacing": [ - "error", - "never" - ], - "object-property-newline": [ - "error", - { - "allowMultiplePropertiesPerLine": true - } - ], - "one-var": [ - "error", - { - "initialized": "never" - } - ], - "operator-linebreak": [ - "error", - "after", - { - "overrides": { - ":": "before", - "?": "before" - } - } - ], - "padded-blocks": [ - "error", - { - "blocks": "never", - "classes": "never", - "switches": "never" - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "prefer-promise-reject-errors": "error", - "quote-props": [ - "error", - "as-needed" - ], - "quotes": [ - "error", - "single" - ], - "rest-spread-spacing": [ - "error", - "never" - ], - "semi": [ - "error", - "always" - ], - "semi-spacing": [ - "error", - { - "after": true, - "before": false - } - ], - "space-before-blocks": [ - "error", - "always" - ], - "space-before-function-paren": [ - "error", - { - "anonymous": "always", - "named": "never", - "asyncArrow": "always" - } - ], - "space-in-parens": [ - "error", - "never" - ], - "space-infix-ops": "error", - "space-unary-ops": [ - "error", - { - "nonwords": false, - "words": true - } - ], - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true, - "exceptions": [ - "*" - ], - "markers": [ - "*package", - "!", - ",", - ":", - "::", - "flow-include" - ] - }, - "line": { - "markers": [ - "*package", - "!", - "/", - ",", - "=" - ] - } - } - ], - "symbol-description": "error", - "template-curly-spacing": [ - "error", - "never" - ], - "template-tag-spacing": [ - "error", - "never" - ], - "unicode-bom": [ - "error", - "never" - ], - "use-isnan": "error", - "valid-typeof": [ - "error", - { - "requireStringLiterals": true - } - ], - "wrap-iife": [ - "error", - "any", - { - "functionPrototypeMethods": true - } - ], - "yield-star-spacing": [ - "error", - "both" - ], - "yoda": [ - "error", - "never" - ] - }, - "overrides": [ - { - "files": [ - "test/**/*.ts" - ], - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-var-requires": "off", - "no-unused-expressions": "off", - "prefer-promise-reject-errors": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true - } - ] - } - } - ] - } -``` - -
- -## 第 1 步:在项目中安装 waffle [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation) {#step-1-install-waffle-in-your-project} - -准备开始,请安装 `ethereum-waffle`。 在本教程中,我会使用 `yarn`,因此,要安装 `ethereum-waffle`,请运行: - -```bash - yarn add --dev ethereum-waffle -``` - -## 第 2 步:编写智能合约 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-a-contract) {#step-2-write-a-smart-contract} - -在本教程中,我会使用 [ERC20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/ded2b0a55c9c13731963ab7b85a70c8e73504bab/contracts/token/ERC20/ERC20.sol) 代币,它们来自 [OpenZepelin](https://openzeppelin.com)。 - -因此,通过使用 `yarn` 安装 `OpenZepelin` 来添加它: - -```bash - yarn add @openzeppelin/contracts -D -``` - -然后在 `src` 目录中创建 `BasicToken.sol` 合约: - -```solidity -pragma solidity ^0.6.0; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -// Example class - a mock class using delivering from ERC20 -contract BasicToken is ERC20 { - constructor(uint256 initialBalance) ERC20("Basic", "BSC") public { - _mint(msg.sender, initialBalance); - } -} - -``` - -## 第 3 步:编译智能合约 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract) {#step-3-compile-your-smart-contract} - -要编译智能合约,在你项目的 `package.json` 中添加以下条目: - -```json -{ - "scripts": { - "build": "waffle" - } -} -``` - -并且在项目的根目录中添加 `waffle.json` 文件。 - -一个 `waffle.json` 配置实例: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -你可以在[这里](https://ethereum-waffle.readthedocs.io/en/latest/configuration.html#configuration)阅读更多关于 Waffle 配置的信息。 - -然后只需运行 `yarn build` 来编译智能合约。 - -你应该看到 Waffle 编译了你的合约,并将由此产生的 JSON 输出放置在 `build` 目录内。 - -
-BasicToken.json - -```json - { - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "evm": { - "bytecode": { - "linkReferences": {}, - "object": "60806040523480156200001157600080fd5b506040516200153938038062001539833981810160405260208110156200003757600080fd5b81019080805190602001909291905050506040518060400160405280600581526020017f42617369630000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f42534300000000000000000000000000000000000000000000000000000000008152508160039080519060200190620000cc92919062000389565b508060049080519060200190620000e592919062000389565b506012600560006101000a81548160ff021916908360ff16021790555050506200011633826200011d60201b60201c565b5062000438565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620001c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001d560008383620002fb60201b60201c565b620001f1816002546200030060201b62000f2d1790919060201c565b6002819055506200024f816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200030060201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b6000808284019050838110156200037f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003cc57805160ff1916838001178555620003fd565b82800160010185558215620003fd579182015b82811115620003fc578251825591602001919060010190620003df565b5b5090506200040c919062000410565b5090565b6200043591905b808211156200043157600081600090555060010162000417565b5090565b90565b6110f180620004486000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH3 0x11 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH3 0x1539 CODESIZE SUB DUP1 PUSH3 0x1539 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH3 0x37 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4261736963000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x3 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x4253430000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x3 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xCC SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP DUP1 PUSH1 0x4 SWAP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 PUSH3 0xE5 SWAP3 SWAP2 SWAP1 PUSH3 0x389 JUMP JUMPDEST POP PUSH1 0x12 PUSH1 0x5 PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP POP POP PUSH3 0x116 CALLER DUP3 PUSH3 0x11D PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST POP PUSH3 0x438 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH3 0x1C1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1F DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x45524332303A206D696E7420746F20746865207A65726F206164647265737300 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH3 0x1D5 PUSH1 0x0 DUP4 DUP4 PUSH3 0x2FB PUSH1 0x20 SHL PUSH1 0x20 SHR JUMP JUMPDEST PUSH3 0x1F1 DUP2 PUSH1 0x2 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x24F DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH3 0x300 PUSH1 0x20 SHL PUSH3 0xF2D OR SWAP1 SWAP2 SWAP1 PUSH1 0x20 SHR JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH3 0x37F JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH3 0x3CC JUMPI DUP1 MLOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH3 0x3FD JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH3 0x3FD JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH3 0x3FC JUMPI DUP3 MLOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH3 0x3DF JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH3 0x40C SWAP2 SWAP1 PUSH3 0x410 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST PUSH3 0x435 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x431 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x417 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x10F1 DUP1 PUSH3 0x448 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 POP DUP1 SWAP2 POP POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 DUP5 ADD SWAP1 POP DUP4 DUP2 LT ISZERO PUSH2 0xFAB JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x1B DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 DUP2 MSTORE POP PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST POP POP POP JUMP INVALID GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220746F20746865207A65726F2061 PUSH5 0x6472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH2 0x7070 PUSH19 0x6F766520746F20746865207A65726F20616464 PUSH19 0x65737345524332303A207472616E7366657220 PUSH2 0x6D6F PUSH22 0x6E7420657863656564732062616C616E636545524332 ADDRESS GASPRICE KECCAK256 PUSH21 0x72616E7366657220616D6F756E7420657863656564 PUSH20 0x20616C6C6F77616E636545524332303A20747261 PUSH15 0x736665722066726F6D20746865207A PUSH6 0x726F20616464 PUSH19 0x65737345524332303A20617070726F76652066 PUSH19 0x6F6D20746865207A65726F2061646472657373 GASLIMIT MSTORE NUMBER ORIGIN ADDRESS GASPRICE KECCAK256 PUSH5 0x6563726561 PUSH20 0x656420616C6C6F77616E63652062656C6F77207A PUSH6 0x726FA2646970 PUSH7 0x735822122081C8 BLOCKHASH CREATE DUP8 0xCE 0xF9 0x2F 0xEC 0xCB SUB STATICCALL 0xDC PUSH8 0x8B2708C331896EC5 NUMBER 0x2B 0x5D 0x4C PUSH8 0x5F27B6D3E664736F PUSH13 0x63430006020033000000000000 ", - "sourceMap": "142:152:5:-:0;;;177:115;8:9:-1;5:2;;;30:1;27;20:12;5:2;177:115:5;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;177:115:5;;;;;;;;;;;;;;;;2013:141:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2093:4;2085:5;:12;;;;;;;;;;;;:::i;:::-;;2117:6;2107:7;:16;;;;;;;;;;;;:::i;:::-;;2145:2;2133:9;;:14;;;;;;;;;;;;;;;;;;2013:141;;252:33:5::1;258:10;270:14;252:5;;;:33;;:::i;:::-;177:115:::0;142:152;;7835:370:2;7937:1;7918:21;;:7;:21;;;;7910:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7986:49;8015:1;8019:7;8028:6;7986:20;;;:49;;:::i;:::-;8061:24;8078:6;8061:12;;:16;;;;;;:24;;;;:::i;:::-;8046:12;:39;;;;8116:30;8139:6;8116:9;:18;8126:7;8116:18;;;;;;;;;;;;;;;;:22;;;;;;:30;;;;:::i;:::-;8095:9;:18;8105:7;8095:18;;;;;;;;;;;;;;;:51;;;;8182:7;8161:37;;8178:1;8161:37;;;8191:6;8161:37;;;;;;;;;;;;;;;;;;7835:370;;:::o;10695:92::-;;;;:::o;874:176:1:-;932:7;951:9;967:1;963;:5;951:17;;991:1;986;:6;;978:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1042:1;1035:8;;;874:176;;;;:::o;142:152:5:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" - }, - "deployedBytecode": { - "linkReferences": {}, - "object": "608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122081c840f087cef92feccb03fadc678b2708c331896ec5432b5d4c675f27b6d3e664736f6c63430006020033", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0xA9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x39509351 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0x39509351 EQ PUSH2 0x25F JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x2C5 JUMPI DUP1 PUSH4 0x95D89B41 EQ PUSH2 0x31D JUMPI DUP1 PUSH4 0xA457C2D7 EQ PUSH2 0x3A0 JUMPI DUP1 PUSH4 0xA9059CBB EQ PUSH2 0x406 JUMPI DUP1 PUSH4 0xDD62ED3E EQ PUSH2 0x46C JUMPI PUSH2 0xA9 JUMP JUMPDEST DUP1 PUSH4 0x6FDDE03 EQ PUSH2 0xAE JUMPI DUP1 PUSH4 0x95EA7B3 EQ PUSH2 0x131 JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x197 JUMPI DUP1 PUSH4 0x23B872DD EQ PUSH2 0x1B5 JUMPI DUP1 PUSH4 0x313CE567 EQ PUSH2 0x23B JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xB6 PUSH2 0x4E4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xF6 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xDB JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x123 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x17D PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x147 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x586 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x19F PUSH2 0x5A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x221 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x1CB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5AE JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x243 PUSH2 0x687 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x2AB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x275 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x69E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x307 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2DB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x751 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x325 PUSH2 0x799 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x365 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0x34A JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x392 JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x3EC PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x3B6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x83B JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x452 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x41C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x908 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x4CE PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x482 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x926 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x60 PUSH1 0x3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x57C JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x551 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x57C JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x55F JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x59A PUSH2 0x593 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x2 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x5BB DUP5 DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH2 0x67C DUP5 PUSH2 0x5C7 PUSH2 0x9AD JUMP JUMPDEST PUSH2 0x677 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x28 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1026 PUSH1 0x28 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 DUP12 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 PUSH2 0x62D PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x747 PUSH2 0x6AB PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x742 DUP6 PUSH1 0x1 PUSH1 0x0 PUSH2 0x6BC PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP10 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 PUSH1 0x4 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0x831 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0x806 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0x831 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0x814 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x8FE PUSH2 0x848 PUSH2 0x9AD JUMP JUMPDEST DUP5 PUSH2 0x8F9 DUP6 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1097 PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x1 PUSH1 0x0 PUSH2 0x872 PUSH2 0x9AD JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP11 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH2 0x9B5 JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x91C PUSH2 0x915 PUSH2 0x9AD JUMP JUMPDEST DUP5 DUP5 PUSH2 0xBAC JUMP JUMPDEST PUSH1 0x1 SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD SWAP1 POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 CALLER SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA3B JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x24 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1073 PUSH1 0x24 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xAC1 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x22 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFDE PUSH1 0x22 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x8C5BE1E5EBEC7D5BD14F71427D1E84F3DD0314C0F7B2291E5B200AC8C7C3B925 DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xC32 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x25 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x104E PUSH1 0x25 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xCB8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x23 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0xFBB PUSH1 0x23 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0xCC3 DUP4 DUP4 DUP4 PUSH2 0xFB5 JUMP JUMPDEST PUSH2 0xD2E DUP2 PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x26 DUP2 MSTORE PUSH1 0x20 ADD PUSH2 0x1000 PUSH1 0x26 SWAP2 CODECOPY PUSH1 0x0 DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xE6D SWAP1 SWAP3 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP PUSH2 0xDC1 DUP2 PUSH1 0x0 DUP1 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SLOAD PUSH2 0xF2D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x0 DUP1 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 DUP2 SWAP1 SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xDDF252AD1BE2C89B69C2B068FC378DAA952BA7F163C4A11628F55A4DF523B3EF DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 DUP4 GT ISZERO DUP3 SWAP1 PUSH2 0xF1A JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xEDF JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xEC4 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0xF0C JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP PUSH1 0x0 DUP4 DUP6 SUB SWAP1 P -``` -
- -## 第 4 步:测试智能合约 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-test-your-smart-contract} - -### 第 4.1 步:安装必要依赖项 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-1} - -我们成功编写智能合同后,就可以对其进行测试。 我们将使用 `Waffle` 来进行测试。 - -`Waffle` 的测试是使用 `Mocha` 和 `Chai` 一起编写的。 我们可以使用不同的测试环境,但 `Waffle` 匹配器只适用于 `Chai`。 - -因此,我们需要将 `Chai` 添加到我们的依赖关系中: - -```bash - yarn add --dev mocha chai -``` - -### 第 4.2 步:创建测试文件 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests) {#step-4-2} - -要编写测试,我们需要在测试目录中创建 `BasicToken.test.ts` 文件。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import BasicToken from "../build/BasicToken.json" - -use(solidity) - -describe("BasicToken", () => { - const [wallet, walletTo] = new MockProvider().getWallets() - let token: Contract - - beforeEach(async () => { - token = await deployContract(wallet, BasicToken, [1000]) - }) -}) -``` - -因此,我们使用 `Waffle` 的 `deployContract` 方法来部署我们的代币。 对于参数来说,我们应该传递 `wallet`、我们合约的已编译 json 文件和默认余额。 - -`Waffle` 也允许我们创建一个 `wallet`,这使得部署合约变得很容易。 - -你可以在[这里](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#getting-wallets)阅读更多关于 `wallet` 的信息,并且你可以在[这里](https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html?highlight=wallet#deploying-contracts)阅读更多关于部署功能的信息。 - -让我们写一个简单的测试来检查钱包的余额。 由于我们在部署合约期间提交了 1000 的价值,所以钱包余额必须是 1000 个代币,我们可以在第一次测试中检查。 - -```ts -it("Assigns initial balance", async () => { - expect(await token.balanceOf(wallet.address)).to.equal(1000) -}) -``` - -要运行测试,请使用 `yarn test` - -### 第 4.3 步:触发事件 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#emitting-events) {#step-4-3} - -在本教程中,我想向你展示 `Waffle` 最有用的匹配器,所以让我们从第一个开始。 - -`Waffle` 允许我们测试在哪里发出了哪些事件。 - -在本教程中,我将测试我们合约的 `transfer` 方法。 - -在这个测试中,我会用一个钱包向另一个钱包转账,然后检查 `Transfer` 事件是否被调用。 - -```ts -it("Transfer emits event", async () => { - await expect(token.transfer(walletTo.address, 7)) - .to.emit(token, "Transfer") - .withArgs(wallet.address, walletTo.address, 7) -}) -``` - -另外,这个匹配器的一大优点是,通过将 `withArgs` 添加到我们的测试中,我们可以检查调用该事件时使用了哪些参数。 - -这将可以确保我们的函数被正确地调用! - -### 第 4.4 步:回滚时显示消息 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#revert-with-message) {#step-4-4} - -`Waffle` 允许我们测试回滚时显示哪些消息。 - -我们在测试中将使用 `revertedWith` 匹配器来对它进行检查。 - -我们可以编写一个测试,我们将在测试中进行一笔大于我们钱包金额的转帐。 然后,我们将检查交易回滚时显示确切的消息! - -```ts -it("Can not transfer above the amount", async () => { - await expect(token.transfer(walletTo.address, 1007)).to.be.revertedWith( - "VM Exception while processing transaction: revert ERC20: transfer amount exceeds balance" - ) -}) -``` - -### 第 4.5 步:改变代币余额 [文档链接](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html?highlight=changeBalance#change-balance) {#step-4-5} - -`Waffle` 允许我们检查钱包余额的变化! - -我们可以使用 `changeTokenBalance` 匹配器来检查余额变化或使用 `changeTokenBalances` 检查多个帐户。 - -匹配器可以接受 `numbers`、`strings` 和 `BigNumbers` 作为余额变化,但是地址应该指定为钱包或合约。 - -我们来编写下一个测试: - -```ts -it("Send transaction changes receiver balance", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalance(walletTo, 200) -}) -``` - -以上是对单个钱包的测试。 - -下一个测试针对多个钱包。 - -```ts -it("Send transaction changes sender and receiver balances", async () => { - await expect(() => - wallet.sendTransaction({ to: walletTo.address, gasPrice: 0, value: 200 }) - ).to.changeBalances([wallet, walletTo], [-200, 200]) -}) -``` - -该交易应作为回调(我们需要在调用之前检查余额)或作为交易响应传递。 - -## 恭喜你 {#congratulations} - -**恭喜你! 你通过这个教程,成功完成了测试。 你已经迈出了使用 Waffle 测试智能合约的第一大步。** - -**你可以在[这里](https://github.com/VladStarostenko/tutorial-for-ethereum-org-website)找到本教程的代码。** - -**更多关于 `Waffle` 的文档可在这里获取 。 diff --git a/public/content/translations/zh/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md b/public/content/translations/zh/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md deleted file mode 100644 index 8f9aa7ad2c1..00000000000 --- a/public/content/translations/zh/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/index.md +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: "Waffle:动态模拟和测试合约调用" -description: "使用动态模拟和测试合约调用的高级 Waffle 教程" -author: "Daniel Izdebski" -tags: [ "waffle", "智能合同", "Solidity", "测试", "模拟" ] -skill: intermediate -lang: zh -published: 2020-11-14 ---- - -## 本教程是关于什么的? {#what-is-this-tutorial-about} - -在本教程中,你将学习如何: - -- 使用动态模拟 -- 测试智能合约之间的交互 - -本文假定: - -- 你已经知道如何用 `Solidity` 编写简单的智能合约 -- 你熟悉 `JavaScript` 和 `TypeScript` -- 你已经完成其他 `Waffle` 教程或对其略知一二 - -## 动态模拟 {#dynamic-mocking} - -为什么动态模拟很有用? 它允许我们编写单元测试,而不是集成测试。 这是什么意思呢? 这意味着我们不必担心智能合约的依赖项,因此我们可以完全隔离地测试所有合约。 让我演示一下如何才能实现。 - -### **1. 项目** {#1-project} - -在开始之前,我们需要准备一个简单的 node.js 项目: - -```bash -mkdir dynamic-mocking -cd dynamic-mocking -mkdir contracts src - -yarn init -# or if you're using npm -npm init -``` - -让我们从添加 typescript 和测试依赖项开始——mocha 和 chai: - -```bash -yarn add --dev @types/chai @types/mocha chai mocha ts-node typescript -# or if you're using npm -npm install @types/chai @types/mocha chai mocha ts-node typescript --save-dev -``` - -现在让我们添加 `Waffle` 和 `ethers`: - -```bash -yarn add --dev ethereum-waffle ethers -# or if you're using npm -npm install ethereum-waffle ethers --save-dev -``` - -你的项目结构现在应该如下所示: - -``` -. -├── contracts -├── package.json -└── test -``` - -### **2. 智能合约** {#2-smart-contract} - -要开始动态模拟,我们需要一个包含依赖项的智能合约。 别担心,我都准备好了! - -这是一个用 `Solidity` 编写的简单智能合约,其唯一目的是检查我们是否有很多钱。 它使用 ERC20 代币来检查我们是否有足够的代币。 将其放在 `./contracts/AmIRichAlready.sol` 中。 - -```solidity -pragma solidity ^0.6.2; - -interface IERC20 { - function balanceOf(address account) external view returns (uint256); -} - -contract AmIRichAlready { - IERC20 private tokenContract; - uint public richness = 1000000 * 10 ** 18; - - constructor (IERC20 _tokenContract) public { - tokenContract = _tokenContract; - } - - function check() public view returns (bool) { - uint balance = tokenContract.balanceOf(msg.sender); - return balance > richness; - } -} -``` - -因为我们想使用动态模拟,所以我们不需要整个 ERC20,这就是我们使用只有一个函数的 IERC20 接口的原因。 - -现在是构建这个合约的时候了! 为此,我们将使用 `Waffle`。 首先,我们将创建一个简单的 `waffle.json` 配置文件,它指定了编译选项。 - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./contracts", - "outputDirectory": "./build" -} -``` - -现在我们已经准备好使用 Waffle 构建合约: - -```bash -npx waffle -``` - -很简单,对吗? 在 `build/` 文件夹中,出现了与合约和接口相对应的两个文件。 我们稍后将使用它们进行测试。 - -### **3. 测试** {#3-testing} - -让我们创建一个名为 `AmIRichAlready.test.ts` 的文件来进行实际测试。 首先,我们必须处理导入。 我们稍后将需要它们: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" -``` - -除了 JS 依赖项,我们还需要导入已构建的合约和接口: - -```typescript -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" -``` - -Waffle 使用 `chai` 进行测试。 但是,在使用它之前,我们必须将 Waffle 的匹配器注入到 chai 本身: - -```typescript -use(solidity) -``` - -我们需要实现 `beforeEach()` 函数,它将在每次测试前重置合约的状态。 让我们先想想我们需要什么。 要部署一个合约,我们需要两样东西:一个钱包和一个已部署的 ERC20 合约,以便将其作为 `AmIRichAlready` 合约的参数传递。 - -首先,我们创建一个钱包: - -```typescript -const [wallet] = new MockProvider().getWallets() -``` - -然后我们需要部署一个 ERC20 合约。 这里是棘手的部分——我们只有一个接口。 这正是 Waffle 大显身手的时候。 Waffle 有一个神奇的 `deployMockContract()` 函数,它只使用接口的 _abi_ 就能创建一个合约: - -```typescript -const mockERC20 = await deployMockContract(wallet, IERC20.abi) -``` - -现在有了钱包和已部署的 ERC20,我们就可以继续部署 `AmIRichAlready` 合约了: - -```typescript -const contract = await deployContract(wallet, AmIRichAlready, [ - mockERC20.address, -]) -``` - -做完这些,我们的 `beforeEach()` 函数就完成了。 到目前为止,你的 `AmIRichAlready.test.ts` 文件应该如下所示: - -```typescript -import { expect, use } from "chai" -import { Contract, utils, Wallet } from "ethers" -import { - deployContract, - deployMockContract, - MockProvider, - solidity, -} from "ethereum-waffle" - -import IERC20 from "../build/IERC20.json" -import AmIRichAlready from "../build/AmIRichAlready.json" - -use(solidity) - -describe("Am I Rich Already", () => { - let mockERC20: Contract - let contract: Contract - let wallet: Wallet - - beforeEach(async () => { - ;[wallet] = new MockProvider().getWallets() - mockERC20 = await deployMockContract(wallet, IERC20.abi) - contract = await deployContract(wallet, AmIRichAlready, [mockERC20.address]) - }) -}) -``` - -让我们为 `AmIRichAlready` 合约编写第一个测试。 你认为我们的测试应该是关于什么的? 没错,你是对的! 我们应该检查我们是否有很多钱:) - -但是等一下。 我们的模拟合约怎么知道要返回什么值呢? 我们还没有为 `balanceOf()` 函数实现任何逻辑。 同样,Waffle 在这里也可以提供帮助。 我们的模拟合约现在有了一些新花招: - -```typescript -await mockERC20.mock..returns() -await mockERC20.mock..withArgs().returns() -``` - -有了这些知识,我们终于可以编写第一个测试了: - -```typescript -it("如果钱包中的代币少于 1000000,则返回 false", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -我们来把这个测试分解成几个部分: - -1. 我们将我们的模拟 ERC20 合约设置为始终返回 999999 个代币的余额。 -2. 检查 `contract.check()` 方法是否返回 `false`。 - -我们已经准备好启动这个家伙了: - -![一个测试通过](./test-one.png) - -所以测试通过了,但是…… 还有一些改进的空间。 `balanceOf()` 函数将始终返回 99999。 我们可以通过指定一个钱包来改进它,让函数为该钱包返回一些东西——就像一个真正的合约一样: - -```typescript -it("如果钱包中的代币少于 1000001,则返回 false", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - expect(await contract.check()).to.be.equal(false) -}) -``` - -到目前为止,我们只测试了我们不够有钱的情况。 让我们来测试一下相反的情况: - -```typescript -it("如果钱包中至少有 1000001 个代币,则返回 true", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("1000001")) - expect(await contract.check()).to.be.equal(true) -}) -``` - -你运行测试…… - -![两个测试通过](test-two.png) - -……就这样,大功告成! 我们的合约似乎按计划进行 :) - -## 测试合约调用 {#testing-contract-calls} - -让我们总结一下到目前为止所做的事情。 我们已经测试了我们的 `AmIRichAlready` 合约的功能,它似乎正常工作。 这意味着我们已经完成了,对吧? 并非如此! Waffle 允许我们进一步测试合约。 但是具体怎么做呢? 那么,在 Waffle 的武器库中,有一个 `calledOnContract()` 和 `calledOnContractWith()` 匹配器。 它们允许我们检查,我们的合约是否调用了 ERC20 模拟合约。 下面是使用其中一个匹配器的基本测试: - -```typescript -it("检查合约是否在 ERC20 代币上调用了 balanceOf", async () => { - await mockERC20.mock.balanceOf.returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContract(mockERC20) -}) -``` - -我们可以更进一步,用我告诉你的另一个匹配器改进这个测试: - -```typescript -it("检查合约是否在 ERC20 代币上用特定钱包调用了 balanceOf", async () => { - await mockERC20.mock.balanceOf - .withArgs(wallet.address) - .returns(utils.parseEther("999999")) - await contract.check() - expect("balanceOf").to.be.calledOnContractWith(mockERC20, [wallet.address]) -}) -``` - -让我们检查测试是否正确: - -![三个测试通过](test-three.png) - -太好了,所有测试都通过了。 - -用 Waffle 测试合约调用非常容易。 而这是最精彩的部分。 这些匹配器对正常合约和模拟合约都有效! 这是因为 Waffle 记录并过滤 EVM 调用,而不是像其他技术的流行测试库那样注入代码。 - -## 终点线 {#the-finish-line} - -恭喜! 现在你知道如何使用 Waffle 来测试合约调用和动态模拟智能合约了。 还有更多有趣的功能等着你去发现。 我建议你深入研究 Waffle 文档。 - -Waffle 的文档可以在[此处](https://ethereum-waffle.readthedocs.io/)查看。 - -本教程的源代码可以在[此处](https://github.com/EthWorks/Waffle/tree/master/examples/dynamic-mocking-and-testing-calls)找到。 - -你可能还感兴趣的教程: - -- [使用 Waffle 测试智能合约](/developers/tutorials/waffle-test-simple-smart-contract/) diff --git a/public/content/translations/zh/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md b/public/content/translations/zh/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md deleted file mode 100644 index 99de7887e55..00000000000 --- a/public/content/translations/zh/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/index.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Waffle:使用 Hardhat 和 ethers 的“hello world”教程" -description: "使用 Hardhat 和 ethers.js 创建你的第一个 Waffle 项目" -author: "MiZiet" -tags: - [ - "waffle", - "智能合同", - "Solidity", - "测试", - "hardhat", - "ethers.js" - ] -skill: beginner -lang: zh -published: 2020-10-16 ---- - -在本 [Waffle](https://ethereum-waffle.readthedocs.io) 教程中,我们将学习如何使用 [hardhat](https://hardhat.org/) 和 [ethers.js](https://docs.ethers.io/v5/) 建立一个简单的“Hello world”智能合约项目。 然后我们将学习如何向我们的智能合约中添加一个新功能,以及如何使用 Waffle 测试它。 - -让我们从创建新项目开始: - -```bash -yarn init -``` - -或 - -```bash -npm init -``` - -并安装所需的软件包: - -```bash -yarn add -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -或 - -```bash -npm install -D hardhat @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-waffle ethereum-waffle chai -``` - -下一步是通过运行 `npx hardhat` 创建一个 Hardhat 示例项目。 - -```bash -888 888 888 888 888 -888 888 888 888 888 -888 888 888 888 888 -8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 -888 888 "88b 888P" d88" 888 888 "88b "88b 888 -888 888 .d888888 888 888 888 888 888 .d888888 888 -888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. -888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 - -👷 欢迎来到 Hardhat v2.0.3 👷‍ - -? 你想做什么?… -❯ 创建一个示例项目 - 创建一个空的 hardhat.config.js - 退出 -``` - -选择 `Create a sample project`(创建示例项目)。 - -我们的项目结构应如下所示: - -``` -MyWaffleProject -├── contracts -│ └── Greeter.sol -├── node_modules -├── scripts -│ └── sample-script.js -├── test -│ └── sample-test.js -├── .gitattributes -├── .gitignore -├── hardhat.config.js -└── package.json -``` - -### 现在让我们来谈谈其中一些文件: {#now-lets-talk} - -- Greeter.sol - 我们用 Solidity 编写的智能合约; - -```solidity -contract Greeter { -string greeting; - -constructor(string memory _greeting) public { -console.log("Deploying a Greeter with greeting:", _greeting); -greeting = _greeting; -} - -function greet() public view returns (string memory) { -return greeting; -} - -function setGreeting(string memory _greeting) public { -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -} -``` - -我们的智能合约可以分为三个部分: - -1. 构造函数 - 我们在其中声明一个名为 `greeting` 的字符串类型变量, -2. 函数 `greet` - 调用时将返回 `greeting` 的函数, -3. 函数 `setGreeting` - 允许我们更改 `greeting` 值的函数。 - -- sample-test.js - 我们的测试文件 - -```js -describe("Greeter", function () { - it("Should return the new greeting once it's changed", async function () { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - expect(await greeter.greet()).to.equal("Hello, world!") - - await greeter.setGreeting("Hola, mundo!") - expect(await greeter.greet()).to.equal("Hola, mundo!") - }) -}) -``` - -### 下一步是编译我们的合约并运行测试: {#compiling-and-testing} - -Waffle 测试使用 Mocha(测试框架)与 Chai(一个断言库)。 你只需运行 `npx hardhat test` 并等待以下消息出现即可。 - -```bash -✓ Should return the new greeting once it's changed -``` - -### 到目前为止,一切看起来都很好,让我们为我们的项目增加一些复杂性吧 {#adding-complexity} - -想象一下这种情况,有人添加了一个空字符串作为问候语。 那可不是个热情的问候,对吧? -我们来确保这种情况不会发生: - -当有人传入空字符串时,我们希望使用 Solidity 的 `revert`。 好在我们可以用 Waffle 的 chai 匹配器 `to.be.revertedWith()` 轻松测试这个功能。 - -```js -it("Should revert when passing an empty string", async () => { - const Greeter = await ethers.getContractFactory("Greeter") - const greeter = await Greeter.deploy("Hello, world!") - - await greeter.deployed() - await expect(greeter.setGreeting("")).to.be.revertedWith( - "Greeting should not be empty" - ) -}) -``` - -看来我们的新测试没有通过: - -```bash -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to 'Hola, mundo!' - ✓ Should return the new greeting once it's changed (1514ms) -Deploying a Greeter with greeting: Hello, world! -Changing greeting from 'Hello, world!' to '' - 1) Should revert when passing an empty string - - - 1 passing (2s) - 1 failing -``` - -让我们在智能合约中实现这个功能: - -```solidity -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -``` - -现在,我们的 setGreeting 函数如下所示: - -```solidity -function setGreeting(string memory _greeting) public { -require(bytes(_greeting).length > 0, "Greeting should not be empty"); -console.log("Changing greeting from '%s' to '%s'", greeting, _greeting); -greeting = _greeting; -} -``` - -让我们再次运行测试: - -```bash -✓ Should return the new greeting once it's changed (1467ms) -✓ Should revert when passing an empty string (276ms) - -2 passing (2s) -``` - -恭喜! 你做到了 :) - -### 结论 {#conclusion} - -我们使用 Waffle、Hardhat 和 ethers.js 制作了一个简单的项目。 我们学习了如何设置项目、添加测试和实现新功能。 - -如需更多用于测试智能合约的出色 chai 匹配器,请查看 [Waffle 的官方文档](https://ethereum-waffle.readthedocs.io/en/latest/matchers.html)。 diff --git a/public/content/translations/zh/developers/tutorials/waffle-test-simple-smart-contract/index.md b/public/content/translations/zh/developers/tutorials/waffle-test-simple-smart-contract/index.md deleted file mode 100644 index 8345dad9c77..00000000000 --- a/public/content/translations/zh/developers/tutorials/waffle-test-simple-smart-contract/index.md +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: "用 Waffle 库测试简单的智能合约" -description: "初学者教程" -author: Ewa Kowalska -tags: [ "智能合同", "Solidity", "Waffle", "测试" ] -skill: beginner -lang: zh -published: 2021-02-26 ---- - -## 在本教程中,你将学习如何 {#in-this-tutorial-youll-learn-how-to} - -- 测试钱包余额的变化 -- 利用指定参数测试事件的触发 -- 断言交易已回滚 - -## 前提条件 {#assumptions} - -- 你能够创建一个新的 JavaScript 或 TypeScript 项目 -- 你拥有一些用 JavaScript 进行测试的基本经验 -- 你使用过一些包管理器,如 yarn 或 npm -- 你拥有关于智能合约和 Solidity 的最基本的知识 - -## 入门 {#getting-started} - -本教程演示了如何使用 yarn 设置和运行测试,但如果你更喜欢用 npm 也没问题——我会提供 Waffle 官方[文档](https://ethereum-waffle.readthedocs.io/en/latest/index.html)的正确参考资料。 - -## 安装依赖项 {#install-dependencies} - -将 ethereum-waffle 和 typescript 依赖项[添加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#installation)到你项目的开发依赖项中。 - -```bash -yarn add --dev ethereum-waffle ts-node typescript @types/jest -``` - -## 智能合约示例 {#example-smart-contract} - -在本教程中,我们将使用一个简单的智能合约示例——EtherSplitter。 它的功能不多,只是允许任何人发送一些 wei,并将其在两个预定义的接收者之间平均分配。 -split 函数要求 wei 的数量为偶数,否则它将回滚。 对于两个接收者,它都会执行一次 wei 转账,然后触发 Transfer 事件。 - -将 EtherSplitter 代码片段放置在 `src/EtherSplitter.sol` 中。 - -```solidity -pragma solidity ^0.6.0; - -contract EtherSplitter { - address payable receiver1; - address payable receiver2; - - event Transfer(address from, address to, uint256 amount); - - constructor(address payable _address1, address payable _address2) public { - receiver1 = _address1; - receiver2 = _address2; - } - - function split() public payable { - require(msg.value % 2 == 0, 'Uneven wei amount not allowed'); - receiver1.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver1, msg.value / 2); - receiver2.transfer(msg.value / 2); - emit Transfer(msg.sender, receiver2, msg.value / 2); - } -} -``` - -## 编译合约 {#compile-the-contract} - -要[编译](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#compiling-the-contract)合约,请将以下条目添加到 package.json 文件中: - -```json -"scripts": { - "build": "waffle" - } -``` - -接下来,在项目根目录中创建 Waffle 配置文件——`waffle.json`——然后将以下配置粘贴到其中: - -```json -{ - "compilerType": "solcjs", - "compilerVersion": "0.6.2", - "sourceDirectory": "./src", - "outputDirectory": "./build" -} -``` - -运行 `yarn build`。 结果,`build` 目录将会出现,其中包含 JSON 格式的已编译的 EtherSplitter 合约。 - -## 测试设置 {#test-setup} - -使用 Waffle 测试需要用到 Chai 匹配器和 Mocha,因此你需要将它们[添加](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#writing-tests)到你的项目中。 更新你的 package.json 文件,并在 scripts 部分添加 `test` 条目: - -```json -"scripts": { - "build": "waffle", - "test": "export NODE_ENV=test && mocha -r ts-node/register 'test/**/*.test.ts'" - } -``` - -如果你想[执行](https://ethereum-waffle.readthedocs.io/en/latest/getting-started.html#running-tests)测试,只需运行 `yarn test` 。 - -## 测试 {#testing} - -现在创建 `test` 目录,并创建新文件 `test\EtherSplitter.test.ts`。 -复制下面的代码片段,并粘贴到我们的测试文件中。 - -```ts -import { expect, use } from "chai" -import { Contract } from "ethers" -import { deployContract, MockProvider, solidity } from "ethereum-waffle" -import EtherSplitter from "../build/EtherSplitter.json" - -use(solidity) - -describe("Ether Splitter", () => { - const [sender, receiver1, receiver2] = new MockProvider().getWallets() - let splitter: Contract - - beforeEach(async () => { - splitter = await deployContract(sender, EtherSplitter, [ - receiver1.address, - receiver2.address, - ]) - }) - - // 在此处添加测试 -}) -``` - -在我们开始之前,先说几句。 -`MockProvider` 提供了一个区块链的模拟版本。 它还提供了模拟钱包,我们可以用它来测试 EtherSplitter 合约。 通过在 provider 上调用 `getWallets()` 方法,我们最多可以获得十个钱包。 在本例中,我们得到三个钱包——一个给发送者,两个给接收者。 - -接下来,我们声明一个名为“splitter”的变量——这是我们的 EtherSplitter 模拟合约。 它在每次执行单个测试前,由 `deployContract` 方法创建。 此方法模拟从作为第一个参数传递的钱包(在我们的例子中是发送者的钱包)部署合约。 第二个参数是被测合约的 ABI 和字节码——我们在此传入 `build` 目录中已编译的 EtherSplitter 合约的 json 文件。 第三个参数是一个包含合约构造函数参数的数组,在我们的例子中,是两个接收者的地址。 - -## changeBalances {#changebalances} - -首先,我们将检查 split 方法是否确实更改了接收者钱包的余额。 如果我们从发送者帐户中分出 50 wei,我们期望两个接收者的余额都增加 25 wei。 我们将使用 Waffle 的 `changeBalances` 匹配器: - -```ts -it("更改账户余额", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalances( - [receiver1, receiver2], - [25, 25] - ) -}) -``` - -作为匹配器的第一个参数,我们传入一个接收者钱包的数组,作为第二个参数,则传入相应账户预期增加额的数组。 -如果我们想检查某个特定钱包的余额,我们也可以使用 `changeBalance` 匹配器,它不需要传入数组,如下例所示: - -```ts -it("更改账户余额", async () => { - await expect(() => splitter.split({ value: 50 })).to.changeBalance( - receiver1, - 25 - ) -}) -``` - -请注意,在 `changeBalance` 和 `changeBalances` 两种情况下,我们都将 split 函数作为回调传递,因为匹配器需要访问调用前后的余额状态。 - -接下来,我们将测试每次 wei 转账后是否都触发了 Transfer 事件。 我们将使用 Waffle 的另一个匹配器: - -## Emit {#emit} - -```ts -it("向第一个接收者转账时触发事件", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver1.address, 25) -}) - -it("向第二个接收者转账时触发事件", async () => { - await expect(splitter.split({ value: 50 })) - .to.emit(splitter, "Transfer") - .withArgs(sender.address, receiver2.address, 25) -}) -``` - -`emit` 匹配器允许我们检查合约在调用方法时是否触发了一个事件。 作为 `emit` 匹配器的参数,我们提供了我们预测将触发事件的模拟合约,以及该事件的名称。 在我们的例子中,模拟合约是 `splitter`,事件名称是 `Transfer`。 我们还可以验证事件触发时所带参数的精确值——我们向 `withArgs` 匹配器传入的参数数量与事件声明所期望的数量相同。 在 EtherSplitter 合约中,我们传入发送者和接收者的地址以及转账的 wei 数量。 - -## revertedWith {#revertedwith} - -作为最后一个例子,我们将检查当 wei 数量为奇数时,交易是否被回滚。 我们将使用 `revertedWith` 匹配器: - -```ts -it("当 Wei 数量为奇数时回滚", async () => { - await expect(splitter.split({ value: 51 })).to.be.revertedWith( - "Uneven wei amount not allowed" - ) -}) -``` - -如果测试通过,它将确保交易确实被回滚了。 但是,我们在 `require` 语句中传递的消息和我们在 `revertedWith` 中期望的消息必须完全匹配。 如果我们回到 EtherSplitter 合约的代码,在针对 wei 数量的 `require` 语句中,我们提供的消息是:‘Uneven wei amount not allowed’。 这与我们在测试中期望的消息相匹配。 如果它们不相等,测试就会失败。 - -## 恭喜! {#congratulations} - -你已经迈出了使用 Waffle 测试智能合约的第一大步! diff --git a/src/data/internalTutorials.json b/src/data/internalTutorials.json index 1d66ef97986..f1691388632 100644 --- a/src/data/internalTutorials.json +++ b/src/data/internalTutorials.json @@ -53,6 +53,5 @@ "understand-the-erc-20-token-smart-contract", "uniswap-v2-annotated-code", "using-websockets", - "waffle-test-simple-smart-contract", "yellow-paper-evm" ] diff --git a/src/data/placeholders/content-developers-tutorials-waffle-dynamic-mocking-and-testing-calls-data.json b/src/data/placeholders/content-developers-tutorials-waffle-dynamic-mocking-and-testing-calls-data.json deleted file mode 100644 index 78101f048fd..00000000000 --- a/src/data/placeholders/content-developers-tutorials-waffle-dynamic-mocking-and-testing-calls-data.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-one.png": { - "hash": "87fb272a", - "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAACCAIAAADej8umAAAACXBIWXMAABYlAAAWJQFJUiTwAAAASElEQVR4nGPIzc1du3bt+fPni4qKAgMDExMTA8EgMTGxrKzM19fXy9lJQ1WVAQ4srC0Kygu8fbyVlZVFUQFERJCfn42VFa4BAL9qFSr7dC2TAAAAAElFTkSuQmCC" - }, - "/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-two.png": { - "hash": "c9ff224d", - "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAADCAIAAAAV0xgDAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAYUlEQVR4nGOorau9dOnSz58/KyoqzM3NnZ2dHcEgLCwsMTHR0dHRRFtLTlqKAQ7kFeS9vb1dXFzMzc29vb0hqh0dHRMTE8PCwp2dne1MjCXFxREaTCxM/MP8lZWVEUJ4AQAIOhqsCVrFUwAAAABJRU5ErkJggg==" - }, - "/content/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/test-three.png": { - "hash": "c5d96e84", - "base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAADCAIAAAAV0xgDAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAaklEQVR4nGNoaWt59vzZ27dvp0+b7uvrm5GREQ0GGWAQHR0d4OOTEB9na2fnYG1tqKXFoKmtWVlZGR8XX1ZWNgkMmpuby8rKjoJBU1PjlIY6E309Pn5+Lg4OLg4OBlsn28SMRA0NDQbiAAByCypJQTzTWgAAAABJRU5ErkJggg==" - } -} \ No newline at end of file From 399404a61ce505d8c2390d35839ad7a001674770 Mon Sep 17 00:00:00 2001 From: Paul Wackerow <54227730+wackerow@users.noreply.github.com> Date: Thu, 26 Feb 2026 12:44:47 -0800 Subject: [PATCH 2/2] fix: rm deprecated tutorials links; replace with others --- .../developers/docs/smart-contracts/testing/index.md | 6 +++--- .../developers/docs/standards/tokens/erc-20/index.md | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/public/content/developers/docs/smart-contracts/testing/index.md b/public/content/developers/docs/smart-contracts/testing/index.md index 45c5f6f0c4c..a2497643ebc 100644 --- a/public/content/developers/docs/smart-contracts/testing/index.md +++ b/public/content/developers/docs/smart-contracts/testing/index.md @@ -311,6 +311,6 @@ The major difference is that bug bounty programs are open to the wider developer ## Tutorials: Smart contract testing on Ethereum {#tutorials} -- [Waffle: Dynamic mocking and testing contract calls](/developers/tutorials/waffle-dynamic-mocking-and-testing-calls/) _– Advanced Waffle tutorial covering dynamic mocking and inter-contract call testing._ -- [Waffle: Hello world with Hardhat and ethers.js](/developers/tutorials/waffle-say-hello-world-with-hardhat-and-ethers/) _– Set up your first Waffle project with Hardhat and ethers.js._ -- [Testing a simple smart contract with Waffle](/developers/tutorials/waffle-test-simple-smart-contract/) _– A beginner's guide to testing smart contract balance changes and events with Waffle._ +- [How to develop and test a dApp on a local, multi-client testnet](/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/) _– Walkthrough of deploying a smart contract to a local testnet and performing tests._ +- [How to mock Solidity smart contracts for testing](/developers/tutorials/how-to-mock-solidity-contracts-for-testing/) _– Intermediate tutorial on how to use mock data and implement unit testing._ +- [How to use Echidna to test smart contracts](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) _– Advanced approached to fuzzing and smart contract testing._ diff --git a/public/content/developers/docs/standards/tokens/erc-20/index.md b/public/content/developers/docs/standards/tokens/erc-20/index.md index c19c3abfe8e..605aef615e9 100644 --- a/public/content/developers/docs/standards/tokens/erc-20/index.md +++ b/public/content/developers/docs/standards/tokens/erc-20/index.md @@ -195,4 +195,3 @@ Some alternative standards have come out of this issue such as [ERC-223](/develo - [ERC-20 with Safety Rails](/developers/tutorials/erc20-with-safety-rails/) _– How to add safeguards to ERC-20 tokens to help users avoid common mistakes._ - [Sending Tokens Using ethers.js](/developers/tutorials/send-token-ethersjs/) _– A beginner-friendly guide to transferring ERC-20 tokens using ethers.js._ - [Some tricks used by scam tokens and how to detect them](/developers/tutorials/scam-token-tricks/) _– A deep-dive into scam ERC-20 token patterns and how to identify them._ -- [Testing ERC-20 tokens with Waffle](/developers/tutorials/testing-erc-20-tokens-with-waffle/) _– How to write and run tests for ERC-20 smart contracts using Waffle._