├── .env.example ├── .gas-snapshot ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── Tests.yaml ├── .gitignore ├── .gitmodules ├── .prettierignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── artifacts ├── AddressWhitelist.json ├── ConditionalTokens.json ├── Finder.json ├── IdentifierWhitelist.json ├── OptimisticOracleV2.json └── Store.json ├── audit └── Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf ├── deploy └── scripts │ └── deploy_adapter.sh ├── docs └── adapter.png ├── foundry.toml ├── package.json ├── src ├── UmaCtfAdapter.sol ├── deploy │ └── Deploy.s.sol ├── interfaces │ ├── IAddressWhitelist.sol │ ├── IAuth.sol │ ├── IBulletinBoard.sol │ ├── IConditionalTokens.sol │ ├── IFinder.sol │ ├── IOptimisticOracleV2.sol │ ├── IOptimisticRequester.sol │ └── IUmaCtfAdapter.sol ├── libraries │ ├── AncillaryDataLib.sol │ ├── PayoutHelperLib.sol │ └── TransferHelper.sol ├── mixins │ ├── Auth.sol │ └── BulletinBoard.sol └── test │ ├── UmaCtfAdapter.t.sol │ ├── dev │ ├── AdapterHelper.sol │ ├── Deployer.sol │ ├── MintableERC20.sol │ ├── OracleStub.sol │ └── TestHelper.sol │ └── mixins │ ├── Auth.t.sol │ └── BulletinBoard.t.sol └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | PK= 2 | CTF= 3 | FINDER= 4 | RPC_URL= 5 | ETHERSCAN_API_KEY= -------------------------------------------------------------------------------- /.gas-snapshot: -------------------------------------------------------------------------------- 1 | AuthTest:testAddAdmin() (gas: 40504) 2 | AuthTest:testAddAdminRevert() (gas: 13031) 3 | AuthTest:testIsAdmin() (gas: 15033) 4 | AuthTest:testOnlyAdminRevert() (gas: 10432) 5 | AuthTest:testOnlyAdminSuccess() (gas: 12455) 6 | AuthTest:testRemoveAdmin() (gas: 31643) 7 | AuthTest:testRenounceAdmin() (gas: 14992) 8 | BulletinBoardTest:testGetLatestUpdate() (gas: 88406) 9 | BulletinBoardTest:testGetUpdate() (gas: 87904) 10 | BulletinBoardTest:testPostUpdate() (gas: 83918) 11 | BulletinBoardTest:testPostUpdateMultiple() (gas: 142834) 12 | UmaCtfAdapterTest:testEmergencyResolve() (gas: 675478) 13 | UmaCtfAdapterTest:testEmergencyResolvePaused() (gas: 671229) 14 | UmaCtfAdapterTest:testEmergencyResolveRevertInvalidPayouts() (gas: 598323) 15 | UmaCtfAdapterTest:testEmergencyResolveRevertNotAdmin() (gas: 601477) 16 | UmaCtfAdapterTest:testEmergencyResolveRevertNotFlagged() (gas: 575401) 17 | UmaCtfAdapterTest:testEmergencyResolveRevertNotInitialized() (gas: 18713) 18 | UmaCtfAdapterTest:testEmergencyResolveRevertSafetyPeriod() (gas: 598715) 19 | UmaCtfAdapterTest:testEmergencyResolveWhenRefundExists() (gas: 1192161) 20 | UmaCtfAdapterTest:testExpectedPayouts() (gas: 709797) 21 | UmaCtfAdapterTest:testExpectedPayoutsRevertEmergencyResolved() (gas: 653477) 22 | UmaCtfAdapterTest:testExpectedPayoutsRevertFlagged() (gas: 596663) 23 | UmaCtfAdapterTest:testExpectedPayoutsRevertIgnorePriceReceived() (gas: 1204243) 24 | UmaCtfAdapterTest:testExpectedPayoutsRevertNotInitialized() (gas: 13378) 25 | UmaCtfAdapterTest:testExpectedPayoutsRevertPaused() (gas: 576629) 26 | UmaCtfAdapterTest:testExpectedPayoutsRevertPriceNotAvailable() (gas: 576207) 27 | UmaCtfAdapterTest:testFlag() (gas: 602025) 28 | UmaCtfAdapterTest:testFlagRevertAlreadyResolved() (gas: 763522) 29 | UmaCtfAdapterTest:testFlagRevertNotAdmin() (gas: 575252) 30 | UmaCtfAdapterTest:testFlagRevertNotInitialized() (gas: 17536) 31 | UmaCtfAdapterTest:testInitialize() (gas: 642401) 32 | UmaCtfAdapterTest:testInitializeCustomLiveness() (gas: 550117) 33 | UmaCtfAdapterTest:testInitializeRevertCustomLiveness() (gas: 450907) 34 | UmaCtfAdapterTest:testInitializeRevertInsufficientRewardBalance() (gas: 313319) 35 | UmaCtfAdapterTest:testInitializeRevertInvalidAncillaryData() (gas: 20703) 36 | UmaCtfAdapterTest:testInitializeRevertOnSameQuestion() (gas: 435731) 37 | UmaCtfAdapterTest:testInitializeRevertUnsupportedRewardToken() (gas: 854121) 38 | UmaCtfAdapterTest:testInitializeZeroRewardAndBond() (gas: 495447) 39 | UmaCtfAdapterTest:testIsValidPayoutArray() (gas: 5136) 40 | UmaCtfAdapterTest:testPause() (gas: 591572) 41 | UmaCtfAdapterTest:testPauseRevertAlreadyResolved() (gas: 763416) 42 | UmaCtfAdapterTest:testPauseRevertNotAdmin() (gas: 584473) 43 | UmaCtfAdapterTest:testPauseRevertNotInitialized() (gas: 17479) 44 | UmaCtfAdapterTest:testPriceDisputed() (gas: 946604) 45 | UmaCtfAdapterTest:testPriceDisputedDvmRespondsIgnore() (gas: 1375973) 46 | UmaCtfAdapterTest:testPriceDisputedDvmRespondsNo() (gas: 1213884) 47 | UmaCtfAdapterTest:testPriceDisputedDvmRespondsYes() (gas: 1253642) 48 | UmaCtfAdapterTest:testPriceDisputedEmergencyResolved() (gas: 839474) 49 | UmaCtfAdapterTest:testPriceDisputedResolveAfterDispute() (gas: 1150552) 50 | UmaCtfAdapterTest:testPriceDisputedRevertNotOO() (gas: 11924) 51 | UmaCtfAdapterTest:testProposed() (gas: 682350) 52 | UmaCtfAdapterTest:testReady() (gas: 780745) 53 | UmaCtfAdapterTest:testReset() (gas: 756605) 54 | UmaCtfAdapterTest:testResetAlreadyReset() (gas: 940360) 55 | UmaCtfAdapterTest:testResetRevertNotInitialized() (gas: 17468) 56 | UmaCtfAdapterTest:testResetRevertResolved() (gas: 774111) 57 | UmaCtfAdapterTest:testResetWhenRefundExists() (gas: 1236548) 58 | UmaCtfAdapterTest:testResolve() (gas: 769747) 59 | UmaCtfAdapterTest:testResolveIgnorePrice() (gas: 1354436) 60 | UmaCtfAdapterTest:testResolveNo() (gas: 729412) 61 | UmaCtfAdapterTest:testResolveRevertAlreadyResolved() (gas: 771678) 62 | UmaCtfAdapterTest:testResolveRevertNotInitialized() (gas: 12894) 63 | UmaCtfAdapterTest:testResolveRevertPaused() (gas: 576364) 64 | UmaCtfAdapterTest:testResolveRevertUnavailablePrice() (gas: 575728) 65 | UmaCtfAdapterTest:testResolveUnknown() (gas: 789128) 66 | UmaCtfAdapterTest:testResolveYes() (gas: 769274) 67 | UmaCtfAdapterTest:testSetup() (gas: 23725) 68 | UmaCtfAdapterTest:testUnflag() (gas: 594373) 69 | UmaCtfAdapterTest:testUnflagRevertAlreadyResolved() (gas: 654621) 70 | UmaCtfAdapterTest:testUnflagRevertNotAdmin() (gas: 600788) 71 | UmaCtfAdapterTest:testUnflagRevertNotInitialized() (gas: 17515) 72 | UmaCtfAdapterTest:testUnflagRevertSafetyPeriodPassed() (gas: 599254) -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socioeconomic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at [`liam@polymarket.com`](mailto:liam@polymarket.com). All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribution Guide 2 | 3 | All contributions are welcome and greatly appreciated! This document serves to outline the process for contributions and help you get set up. 4 | 5 | ### Steps to get started 6 | 7 | 1. Fork this repo 8 | 2. Clone your fork 9 | 3. Follow the [installation instructions](./README.md) in the monorepo's top level README. 10 | 4. Open pull requests with the `WIP` flag against the `main` branch and include a description of the intended change in the PR description. 11 | 12 | Before removing the `WIP` tag and submitting a PR for review, make sure that: 13 | 14 | - it passes our linter checks 15 | - the test suite passes for all packages 16 | - it passes our continuous integration tests 17 | - your fork is up to date with `main` 18 | 19 | ### Branch structure & naming 20 | 21 | Our main branch, `main`, represents the current development state of the codebase. All pull requests should be opened against `main`. 22 | 23 | Name your branch with the format `{fix | feat | refactor }/{ description }` 24 | 25 | - A `fix` addresses a bug or other issue 26 | - A `feat` adds new functionality/interface surface area 27 | - A `refactor` changes no business logic or interfaces, but improves implementation 28 | 29 | ### Additional Details 30 | 31 | If you have any questions, please feel free to reach out to [Liam Kovatch](mailto:liam@polymarket.com) (GitHub [@l-kov](https://github.com/l-kov)) or [Jon Amenechi](mailto:jon@polymarket.com) (GitHub [@JonathanAmenechi](https://github.com/JonathanAmenechi)), or message us on any of our communication channels. We are always happy to help! If you have feedback, bugs, or feature requests, please shoot them our way. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## Overview 5 | 6 | 7 | 8 | ## Description 9 | 10 | 11 | 12 | 13 | ## Notes 14 | 15 | 16 | 17 | ## Action items 18 | 19 | - [ ] Tag issue (bug, enhancement, feature, etc.) 20 | - [ ] Initial discussion/assign team member 21 | - [ ] Move discussion to PR if necessary and when ready 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## Overview 5 | 6 | 7 | 8 | ## Description 9 | 10 | 11 | 12 | ## Testing instructions 13 | 14 | 15 | 16 | ## Types of changes 17 | 18 | 19 | 20 | - [ ] Refactor/enhancement 21 | - [ ] Bug fix/behavior correction 22 | - [ ] New feature 23 | - [ ] Breaking change 24 | - [ ] Other, additional 25 | 26 | ## Notes 27 | 28 | 29 | 30 | ## Status 31 | 32 | 33 | 34 | 35 | - [ ] Prefix PR title with `WIP` if necessary (changes not yet made). 36 | - [ ] Add tests to cover changes as needed. 37 | - [ ] Update documentation/changelog as needed. 38 | - [ ] Verify all tests run correctly in CI and pass. 39 | - [ ] Ready for review/merge. 40 | -------------------------------------------------------------------------------- /.github/workflows/Tests.yaml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | name: test 4 | 5 | jobs: 6 | check: 7 | name: Tests 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | submodules: recursive 13 | 14 | - name: Install Foundry 15 | uses: foundry-rs/foundry-toolchain@v1 16 | with: 17 | version: nightly 18 | 19 | - name: Run tests 20 | run: forge test -vvv 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # folders 2 | node_modules/ 3 | lib 4 | broadcast/ 5 | 6 | *.log 7 | *.tgz 8 | 9 | .env 10 | .env.* 11 | !.env.example 12 | 13 | cache 14 | coverage* 15 | .vscode 16 | dist 17 | out -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/openzeppelin-contracts"] 2 | path = lib/openzeppelin-contracts 3 | url = https://github.com/openzeppelin/openzeppelin-contracts 4 | [submodule "lib/forge-std"] 5 | path = lib/forge-std 6 | url = https://github.com/foundry-rs/forge-std 7 | [submodule "lib/solmate"] 8 | path = lib/solmate 9 | url = https://github.com/transmissions11/solmate 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # folders 2 | artifacts/ 3 | build/ 4 | cache/ 5 | coverage/ 6 | dist/ 7 | lib/ 8 | node_modules/ 9 | typechain/ 10 | 11 | # files 12 | coverage.json 13 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "endOfLine": "auto", 5 | "printWidth": 120, 6 | "singleQuote": false, 7 | "tabWidth": 4, 8 | "trailingComma": "all" 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Polymarket UMA CTF Adapter 2 | 3 | [![Version][version-badge]][version-link] 4 | [![License][license-badge]][license-link] 5 | [![Test][ci-badge]][ci-link] 6 | 7 | [version-badge]: https://img.shields.io/github/v/release/polymarket/uma-ctf-adapter.svg?label=version 8 | [version-link]: https://github.com/Polymarket/uma-ctf-adapter/releases 9 | [license-badge]: https://img.shields.io/github/license/polymarket/uma-ctf-adapter 10 | [license-link]: https://github.com/Polymarket/uma-ctf-adapter/blob/main/LICENSE.md 11 | [ci-badge]: https://github.com/Polymarket/uma-ctf-adapter/workflows/Tests/badge.svg 12 | [ci-link]: https://github.com/Polymarket/uma-ctf-adapter/actions/workflows/Tests.yaml 13 | 14 | ## Overview 15 | 16 | This repository contains contracts used to resolve [Polymarket](https://polymarket.com/) prediction markets via UMA's [optimistic oracle](https://docs.umaproject.org/oracle/optimistic-oracle-interface). 17 | 18 | ## Architecture 19 | ![Contract Architecture](./docs/adapter.png) 20 | 21 | The Adapter is an [oracle](https://github.com/Polymarket/conditional-tokens-contracts/blob/a927b5a52cf9ace712bf1b5fe1d92bf76399e692/contracts/ConditionalTokens.sol#L65) to [Conditional Tokens Framework(CTF)](https://docs.gnosis.io/conditionaltokens/) conditions, which Polymarket prediction markets are based on. 22 | 23 | It fetches resolution data from UMA's Optmistic Oracle and resolves the condition based on said resolution data. 24 | 25 | When a new market is deployed, it is `initialized`, meaning: 26 | 1) The market's parameters(ancillary data, request timestamp, reward token, reward, etc) are stored onchain 27 | 2) The market is [`prepared`](https://github.com/Polymarket/conditional-tokens-contracts/blob/a927b5a52cf9ace712bf1b5fe1d92bf76399e692/contracts/ConditionalTokens.sol#L65) on the CTF contract 28 | 3) A resolution data request is sent out to the Optimistic Oracle 29 | 30 | UMA Proposers will then respond to the request and fetch resolution data offchain. If the resolution data is not disputed, the data will be available to the Adapter after a defined liveness period(currently about 2 hours). 31 | 32 | The first time a request is disputed, the market is automatically `reset`, meaning, a new Optimistic Oracle request is sent out. This ensures that *obviously incorrect disputes do not slow down resolution of the market*. 33 | 34 | If the request is disputed again, this indicates a more fundamental disagreement among proposers and the Optimistic Oracle falls back to UMA's [DVM](https://docs.umaproject.org/getting-started/oracle#umas-data-verification-mechanism) to come to agreement. The DVM will return data after a 48 - 72 hour period. 35 | 36 | After resolution data is available, anyone can call `resolve` which resolves the market using the resolution data. 37 | 38 | 39 | ## Audit 40 | 41 | These contracts have been audited by OpenZeppelin and the report is available [here](./audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf). 42 | 43 | ## Deployments 44 | 45 | See [Deployments](https://github.com/Polymarket/uma-ctf-adapter/releases) 46 | 47 | 48 | ## Development 49 | 50 | Clone the repo: `git clone https://github.com/Polymarket/uma-ctf-adapter.git --recurse-submodules` 51 | 52 | --- 53 | 54 | ### Set-up 55 | 56 | Install [Foundry](https://github.com/foundry-rs/foundry/). 57 | 58 | Foundry has daily updates, run `foundryup` to update `forge` and `cast`. 59 | 60 | To install/update forge dependencies: `forge update` 61 | 62 | To build contracts: `forge build` 63 | 64 | --- 65 | 66 | ### Testing 67 | 68 | To run all tests: `forge test` 69 | 70 | Set `-vvv` to see a stack trace for a failed test. -------------------------------------------------------------------------------- /artifacts/AddressWhitelist.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addedAddress","type":"address"}],"name":"AddedToWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"removedAddress","type":"address"}],"name":"RemovedFromWhitelist","type":"event"},{"inputs":[{"internalType":"address","name":"newElement","type":"address"}],"name":"addToWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getWhitelist","outputs":[{"internalType":"address[]","name":"activeWhitelist","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"elementToCheck","type":"address"}],"name":"isOnWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"elementToRemove","type":"address"}],"name":"removeFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"enum AddressWhitelist.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"whitelistIndices","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}], 3 | "bytecode": { 4 | "object": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460ff60a01b1916600160a01b17905561095f806100746000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638da5cb5b116100665780638da5cb5b146101085780639b19251a14610119578063d01f63f514610149578063e43252d71461015e578063f2fde38b1461017157600080fd5b806337797c08146100985780633a3ab672146100c8578063715018a6146100eb5780638ab1d681146100f5575b600080fd5b6100ab6100a6366004610840565b610184565b6040516001600160a01b0390911681526020015b60405180910390f35b6100db6100d6366004610812565b6101ae565b60405190151581526020016100bf565b6100f36101fc565b005b6100f3610103366004610812565b610279565b6000546001600160a01b03166100ab565b61013c610127366004610812565b60016020526000908152604090205460ff1681565b6040516100bf91906108a5565b610151610364565b6040516100bf9190610858565b6100f361016c366004610812565b610550565b6100f361017f366004610812565b6106cd565b6002818154811061019457600080fd5b6000918252602090912001546001600160a01b0316905081565b60006101b86107b7565b60016001600160a01b03831660009081526001602052604090205460ff1660028111156101f557634e487b7160e01b600052602160045260246000fd5b1492915050565b6000546001600160a01b0316331461022f5760405162461bcd60e51b8152600401610226906108cd565b60405180910390fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6102816107b7565b6102936000805460ff60a01b19169055565b6000546001600160a01b031633146102bd5760405162461bcd60e51b8152600401610226906108cd565b60026001600160a01b03821660009081526001602052604090205460ff1660028111156102fa57634e487b7160e01b600052602160045260246000fd5b14610349576001600160a01b038116600081815260016020526040808220805460ff19166002179055517fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df7579190a25b6103616000805460ff60a01b1916600160a01b179055565b50565b606061036e6107b7565b6000805b60025481101561040f576001806000600284815481106103a257634e487b7160e01b600052603260045260246000fd5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1660028111156103e957634e487b7160e01b600052602160045260246000fd5b14156103fd57816103f981610902565b9250505b8061040781610902565b915050610372565b508067ffffffffffffffff81111561043757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610460578160200160208202803683370190505b5091506000905060005b60025481101561054b5760006002828154811061049757634e487b7160e01b600052603260045260246000fd5b6000918252602090912001546001600160a01b0316905060016001600160a01b03821660009081526001602052604090205460ff1660028111156104eb57634e487b7160e01b600052602160045260246000fd5b1415610538578084848151811061051257634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528261053481610902565b9350505b508061054381610902565b91505061046a565b505090565b6105586107b7565b61056a6000805460ff60a01b19169055565b6000546001600160a01b031633146105945760405162461bcd60e51b8152600401610226906108cd565b60016001600160a01b03821660009081526001602052604090205460ff1660028111156105d157634e487b7160e01b600052602160045260246000fd5b14156105dc57610349565b6001600160a01b03811660009081526001602052604081205460ff16600281111561061757634e487b7160e01b600052602160045260246000fd5b141561066957600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b0383161790555b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab039190a26103616000805460ff60a01b1916600160a01b179055565b6000546001600160a01b031633146106f75760405162461bcd60e51b8152600401610226906108cd565b6001600160a01b03811661075c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610226565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b600054600160a01b900460ff166108105760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610226565b565b600060208284031215610823578081fd5b81356001600160a01b0381168114610839578182fd5b9392505050565b600060208284031215610851578081fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156108995783516001600160a01b031683529284019291840191600101610874565b50909695505050505050565b60208101600383106108c757634e487b7160e01b600052602160045260246000fd5b91905290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060001982141561092257634e487b7160e01b81526011600452602481fd5b506001019056fea2646970667358221220510af749c43f1e7931e65e1e33b68e4cae324ca9b69946ac9771e8ea756832c164736f6c63430008040033" 5 | } 6 | } -------------------------------------------------------------------------------- /artifacts/Finder.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"interfaceName","type":"bytes32"},{"indexed":true,"internalType":"address","name":"newImplementationAddress","type":"address"}],"name":"InterfaceImplementationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes32","name":"interfaceName","type":"bytes32"},{"internalType":"address","name":"implementationAddress","type":"address"}],"name":"changeImplementationAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"interfaceName","type":"bytes32"}],"name":"getImplementationAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"interfacesImplemented","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}], 3 | "bytecode": { 4 | "object": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061043c806100616000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806331f9665e14610067578063715018a61461007c5780638da5cb5b14610084578063aafd5e40146100ad578063cc48f4db146100c0578063f2fde38b146100e9575b600080fd5b61007a6100753660046103a6565b6100fc565b005b61007a610188565b6000546001600160a01b03165b6040516001600160a01b03909116815260200160405180910390f35b6100916100bb36600461038e565b6101fc565b6100916100ce36600461038e565b6001602052600090815260409020546001600160a01b031681565b61007a6100f736600461036d565b610267565b6000546001600160a01b0316331461012f5760405162461bcd60e51b8152600401610126906103d1565b60405180910390fd5b60008281526001602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917fb29aa13e555039289e0513962835b00fcc6e4a265ae8f99e68e5b90d5406fe489190a35050565b6000546001600160a01b031633146101b25760405162461bcd60e51b8152600401610126906103d1565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000818152600160205260408120546001600160a01b0316806102615760405162461bcd60e51b815260206004820152601860248201527f496d706c656d656e746174696f6e206e6f7420666f756e6400000000000000006044820152606401610126565b92915050565b6000546001600160a01b031633146102915760405162461bcd60e51b8152600401610126906103d1565b6001600160a01b0381166102f65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610126565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b80356001600160a01b038116811461036857600080fd5b919050565b60006020828403121561037e578081fd5b61038782610351565b9392505050565b60006020828403121561039f578081fd5b5035919050565b600080604083850312156103b8578081fd5b823591506103c860208401610351565b90509250929050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea2646970667358221220e94e266f032854b028bf29acf009d6d2c1491d1f82305c353042778582cd4cc864736f6c63430008040033" 5 | } 6 | } -------------------------------------------------------------------------------- /artifacts/IdentifierWhitelist.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"SupportedIdentifierAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"SupportedIdentifierRemoved","type":"event"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"addSupportedIdentifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"isIdentifierSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"}],"name":"removeSupportedIdentifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}], 3 | "bytecode": { 4 | "object": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061041d806100616000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806310a7e20114610067578063715018a61461007c5780638da5cb5b146100845780638e0d3ca7146100a457806390978d1b146100b7578063f2fde38b146100ea575b600080fd5b61007a61007536600461039a565b6100fd565b005b61007a61018d565b6000546040516001600160a01b0390911681526020015b60405180910390f35b61007a6100b236600461039a565b610201565b6100da6100c536600461039a565b60009081526001602052604090205460ff1690565b604051901515815260200161009b565b61007a6100f836600461036c565b610282565b6000546001600160a01b031633146101305760405162461bcd60e51b8152600401610127906103b2565b60405180910390fd5b60008181526001602052604090205460ff1661018a576000818152600160208190526040808320805460ff19169092179091555182917fa0ca1076d765c13772089a90b5121cf6ddf63c9f7891c4e5031adbc85936b27691a25b50565b6000546001600160a01b031633146101b75760405162461bcd60e51b8152600401610127906103b2565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b0316331461022b5760405162461bcd60e51b8152600401610127906103b2565b60008181526001602052604090205460ff161561018a57600081815260016020526040808220805460ff191690555182917fefdf15ca0f9402bd4e933b0edb0db65b23cc50d27cb010d8abcadaae4fa944e591a250565b6000546001600160a01b031633146102ac5760405162461bcd60e51b8152600401610127906103b2565b6001600160a01b0381166103115760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610127565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006020828403121561037d578081fd5b81356001600160a01b0381168114610393578182fd5b9392505050565b6000602082840312156103ab578081fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260408201526060019056fea2646970667358221220160ee2321ee592f6fd77e83afbc188200fa16c254fbd9e363d50c912311836ca64736f6c63430008040033" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /artifacts/OptimisticOracleV2.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [{"inputs":[{"internalType":"uint256","name":"_liveness","type":"uint256"},{"internalType":"address","name":"_finderAddress","type":"address"},{"internalType":"address","name":"_timerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"indexed":false,"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"DisputePrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"indexed":false,"internalType":"int256","name":"proposedPrice","type":"int256"},{"indexed":false,"internalType":"uint256","name":"expirationTimestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"ProposePrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"indexed":false,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"finalFee","type":"uint256"}],"name":"RequestPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requester","type":"address"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":true,"internalType":"address","name":"disputer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"indexed":false,"internalType":"int256","name":"price","type":"int256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"}],"name":"Settle","type":"event"},{"inputs":[],"name":"OO_ANCILLARY_DATA_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOO_EARLY_RESPONSE","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ancillaryBytesLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultLiveness","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"disputePrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"disputer","type":"address"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"disputePriceFor","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finder","outputs":[{"internalType":"contract FinderInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"getRequest","outputs":[{"components":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"components":[{"internalType":"bool","name":"eventBased","type":"bool"},{"internalType":"bool","name":"refundOnDispute","type":"bool"},{"internalType":"bool","name":"callbackOnPriceProposed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceDisputed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceSettled","type":"bool"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct OptimisticOracleV2Interface.RequestSettings","name":"requestSettings","type":"tuple"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"internalType":"struct OptimisticOracleV2Interface.Request","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"getState","outputs":[{"internalType":"enum OptimisticOracleV2Interface.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"hasPrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"proposePrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"int256","name":"proposedPrice","type":"int256"}],"name":"proposePriceFor","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"requestPrice","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requests","outputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"disputer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"},{"internalType":"bool","name":"settled","type":"bool"},{"components":[{"internalType":"bool","name":"eventBased","type":"bool"},{"internalType":"bool","name":"refundOnDispute","type":"bool"},{"internalType":"bool","name":"callbackOnPriceProposed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceDisputed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceSettled","type":"bool"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"internalType":"struct OptimisticOracleV2Interface.RequestSettings","name":"requestSettings","type":"tuple"},{"internalType":"int256","name":"proposedPrice","type":"int256"},{"internalType":"int256","name":"resolvedPrice","type":"int256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"},{"internalType":"uint256","name":"finalFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"uint256","name":"bond","type":"uint256"}],"name":"setBond","outputs":[{"internalType":"uint256","name":"totalBond","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"bool","name":"callbackOnPriceProposed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceDisputed","type":"bool"},{"internalType":"bool","name":"callbackOnPriceSettled","type":"bool"}],"name":"setCallbacks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"uint256","name":"customLiveness","type":"uint256"}],"name":"setCustomLiveness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"setEventBased","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"setRefundOnDispute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"settle","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes","name":"ancillaryData","type":"bytes"}],"name":"settleAndGetPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"ancillaryData","type":"bytes"},{"internalType":"address","name":"requester","type":"address"}],"name":"stampAncillaryData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}], 3 | "bytecode": { 4 | "object": "0x60806040523480156200001157600080fd5b506040516200437738038062004377833981016040819052620000349162000149565b60018054600160a01b6001600160a01b038481166001600160a81b03199093169290921717909155600280546001600160a01b0319169184169190911790556200007e8362000089565b50506003556200018a565b63bb7448008110620000d75760405162461bcd60e51b81526020600482015260126024820152714c6976656e65737320746f6f206c6172676560701b60448201526064015b60405180910390fd5b60008111620001295760405162461bcd60e51b815260206004820152601460248201527f4c6976656e6573732063616e6e6f7420626520300000000000000000000000006044820152606401620000ce565b50565b80516001600160a01b03811681146200014457600080fd5b919050565b6000806000606084860312156200015f57600080fd5b8351925062000171602085016200012c565b915062000181604085016200012c565b90509250925092565b6141dd806200019a6000396000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80639d866985116100ee578063ba4b930c11610097578063f327b07511610071578063f327b0751461049f578063fba7f1e3146104b2578063fe4e1983146104c5578063ff8c1a8c146104ce57600080fd5b8063ba4b930c14610453578063bc58ccaa14610473578063c371dda71461049657600080fd5b8063af5d2f39116100c8578063af5d2f3914610400578063b8b4f90814610420578063b9a3c84c1461043357600080fd5b80639d866985146102bd578063a9904f9b146103cd578063ad5a755a146103ed57600080fd5b80634ccb56f51161015057806376c7823f1161012a57806376c7823f146102845780637c82288f1461029757806391f58dcb146102aa57600080fd5b80634ccb56f51461025657806353b592391461025e5780635e9a79a91461027157600080fd5b806322f8e5661161018157806322f8e5661461022857806329cb924d1461023b578063473c45fe1461024357600080fd5b806311df92f1146101a8578063120698af146101ce5780631c39c38d146101e3575b600080fd5b6101bb6101b63660046136d6565b6104f5565b6040519081526020015b60405180910390f35b6101e16101dc366004613741565b610d2a565b005b6001546102039073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c5565b6101e1610236366004613791565b610e6c565b6101bb610f15565b6101e16102513660046137aa565b610f24565b6101bb611043565b6101bb61026c366004613741565b611053565b6101bb61027f366004613802565b611119565b6101bb610292366004613865565b6111aa565b6101bb6102a53660046138db565b61176f565b6101e16102b8366004613741565b611bed565b6103b76102cb366004613791565b60006020818152918152604090819020805460018201546002830154845160e081018652600385015460ff8082161515835261010082048116151598830198909852620100008104881615159682019690965263010000008604871615156060820152640100000000909504861615156080860152600484015460a0860152600584015460c08601526006840154600785015460088601546009870154600a9097015473ffffffffffffffffffffffffffffffffffffffff968716999587169896851697740100000000000000000000000000000000000000009095049095169594929391929091908a565b6040516101c59a99989796959493929190613959565b6103e06103db366004613802565b611d30565b6040516101c59190613a16565b6101bb6103fb3660046137aa565b611f01565b61041361040e366004613b33565b61202d565b6040516101c59190613bfb565b6101bb61042e366004613c0e565b612042565b6002546102039073ffffffffffffffffffffffffffffffffffffffff1681565b610466610461366004613802565b612052565b6040516101c59190613ca8565b610486610481366004613802565b612068565b60405190151581526020016101c5565b6101bb61200081565b6101e16104ad366004613cf7565b6120d8565b6101bb6104c0366004613802565b612276565b6101bb60035481565b6101bb7f800000000000000000000000000000000000000000000000000000000000000081565b60006104ff612285565b61052c600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b600061053a3388888861230b565b600681111561054b5761054b613c79565b146105b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f7265717565737450726963653a20496e76616c6964000000000000000000000060448201526064015b60405180910390fd5b6105bf61249c565b73ffffffffffffffffffffffffffffffffffffffff166390978d1b876040518263ffffffff1660e01b81526004016105f991815260200190565b60206040518083038186803b15801561061157600080fd5b505afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190613d80565b6106af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f556e737570706f72746564206964656e7469666965720000000000000000000060448201526064016105ae565b6106b761255f565b6040517f3a3ab67200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301529190911690633a3ab6729060240160206040518083038186803b15801561072057600080fd5b505afa158015610734573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107589190613d80565b6107be576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f556e737570706f727465642063757272656e637900000000000000000000000060448201526064016105ae565b6107c6610f15565b85111561082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f54696d657374616d7020696e206675747572650000000000000000000000000060448201526064016105ae565b61083c6035612000613dcc565b845111156108a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f416e63696c6c617279204461746120746f6f206c6f6e6700000000000000000060448201526064016105ae565b60006108b06125d6565b6040517f5b97aadd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301529190911690635b97aadd9060240160206040518083038186803b15801561091957600080fd5b505afa15801561092d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109519190613de3565b600001519050604051806101400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020016000151581526020016040518060e001604052806000151581526020016000151581526020016000151581526020016000151581526020016000151581526020018481526020016000815250815260200160008152602001600081526020016000815260200184815260200182815250600080610a38338b8b8b61264d565b81526020808201929092526040908101600020835181547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9283161783558585015160018401805490921690831617905584830151600283018054606080890151939094167fffffffffffffffffffffff0000000000000000000000000000000000000000009091161774010000000000000000000000000000000000000000921515929092029190911790556080808601518051600385018054978301519683015194830151938301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009098169115157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16919091176101009615158702177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1662010000941515949094027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff1693909317630100000092151592909202919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000009515159590950294909417905560a080840151600483015560c0938401516005830155840151600682015591830151600783015560e08301516008830155820151600982015561012090910151600a909101558215610c7757610c7773ffffffffffffffffffffffffffffffffffffffff8516333086612686565b3373ffffffffffffffffffffffffffffffffffffffff167ff1679315ff325c257a944e0ca1bfe7b26616039e9511f9610d4ba3eca851027b888888888887604051610cc796959493929190613e25565b60405180910390a2610cda816002612762565b915050610d21600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b95945050505050565b610d32612285565b610d5f600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6001610d6d3385858561230b565b6006811115610d7e57610d7e613c79565b14610de5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f7365744576656e7442617365643a20526571756573746564000000000000000060448201526064016105ae565b6000610df33385858561276e565b60030180546101017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090911617905550610e67600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b505050565b60015473ffffffffffffffffffffffffffffffffffffffff16610e8e57600080fd5b6001546040517f22f8e5660000000000000000000000000000000000000000000000000000000081526004810183905273ffffffffffffffffffffffffffffffffffffffff909116906322f8e56690602401600060405180830381600087803b158015610efa57600080fd5b505af1158015610f0e573d6000803e3d6000fd5b5050505050565b6000610f1f612797565b905090565b610f2c612285565b610f59600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6001610f673386868661230b565b6006811115610f7857610f78613c79565b14610fdf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f736574437573746f6d4c6976656e6573733a205265717565737465640000000060448201526064016105ae565b610fe88161285d565b80610ff53386868661276e565b6005015561103d600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b50505050565b6110506035612000613dcc565b81565b600061105d612285565b61108a600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b60066110983386868661230b565b60068111156110a9576110a9613c79565b146110bc576110ba33858585612937565b505b6110c83385858561276e565b600701549050611112600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b9392505050565b6000611123612285565b611150600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b61115c85858585612937565b90506111a2600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b949350505050565b60006111b4612285565b6111e1600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b73ffffffffffffffffffffffffffffffffffffffff861661125e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f64697370757465722061646472657373206d757374206265206e6f6e2030000060448201526064016105ae565b600261126c8686868661230b565b600681111561127d5761127d613c79565b146112e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f646973707574655072696365466f723a2050726f706f7365640000000000000060448201526064016105ae565b60006112f28686868661276e565b6001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600a81015460048201549192509061134c8183612d96565b9350831561137b57600283015461137b9073ffffffffffffffffffffffffffffffffffffffff16333087612686565b60006113856125d6565b9050600061139c61139586612da2565b8590612d96565b9050801561146c5760028501546113ca9073ffffffffffffffffffffffffffffffffffffffff168383612db5565b6113d26125d6565b60028601546040805160208101825284815290517f8659d23200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015290516024820152911690638659d23290604401600060405180830381600087803b15801561145357600080fd5b505af1158015611467573d6000803e3d6000fd5b505050505b611474612ec2565b73ffffffffffffffffffffffffffffffffffffffff1663216666a48a61149a888c612f39565b6114a48b8f612f84565b6040518463ffffffff1660e01b81526004016114c293929190613e78565b600060405180830381600087803b1580156114dc57600080fd5b505af11580156114f0573d6000803e3d6000fd5b50505050600080866009015411801561151257506003860154610100900460ff165b156115495750600985018054600090915560028601546115499073ffffffffffffffffffffffffffffffffffffffff168c83612fc6565b8b73ffffffffffffffffffffffffffffffffffffffff168660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff167f5165909c3d1c01c5d1e121ac6f6d01dda1ba24bc9e1f975b5a375339c15be7f38d8d8d8c600601546040516115eb9493929190613e97565b60405180910390a4611637600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b73ffffffffffffffffffffffffffffffffffffffff8b163b15158015611668575060038601546301000000900460ff165b156116f8576040517f0d8f237200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c1690630d8f2372906116c5908d908d908d908790600401613e97565b600060405180830381600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b505050505b611725600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b505050505050610d21600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b6000611779612285565b6117a6600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b73ffffffffffffffffffffffffffffffffffffffff8716611823576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f70726f706f7365722061646472657373206d757374206265206e6f6e2030000060448201526064016105ae565b60016118318787878761230b565b600681111561184257611842613c79565b146118a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f70726f706f73655072696365466f723a2052657175657374656400000000000060448201526064016105ae565b60006118b78787878761276e565b600381015490915060ff1615611951577f8000000000000000000000000000000000000000000000000000000000000000831415611951576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616e6e6f742070726f706f73652027746f6f206561726c792700000000000060448201526064016105ae565b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff89161781556006810183905560058101546119bf906119ab576003546119b1565b60058201545b6119b9610f15565b90612d96565b6008820155600a81015460048201546119d791612d96565b91508115611a06576002810154611a069073ffffffffffffffffffffffffffffffffffffffff16333085612686565b6008810154600282015460405173ffffffffffffffffffffffffffffffffffffffff8b8116938b8216937f6e51dd00371aabffa82cd401592f76ed51e98a9ea4b58751c70463a2c78b5ca193611a67938d938d938d938d9390911690613ec7565b60405180910390a3611ab3600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b73ffffffffffffffffffffffffffffffffffffffff87163b15158015611ae35750600381015462010000900460ff165b15611b71576040517f9c2fd1df00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff881690639c2fd1df90611b3e90899089908990600401613e78565b600060405180830381600087803b158015611b5857600080fd5b505af1158015611b6c573d6000803e3d6000fd5b505050505b611b9e600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b50611be3600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b9695505050505050565b611bf5612285565b611c22600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6001611c303385858561230b565b6006811115611c4157611c41613c79565b14611ca8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f736574526566756e644f6e446973707574653a2052657175657374656400000060448201526064016105ae565b6001611cb63385858561276e565b6003018054911515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909216919091179055610e67600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b611dbc6040805161014081018252600080825260208083018290528284018290526060808401839052845160e081018652838152918201839052938101829052928301819052608083810182905260a0840182905260c0840191909152909190820190815260200160008152602001600081526020016000815260200160008152602001600081525090565b611dc4612285565b611dd08585858561276e565b6040805161014081018252825473ffffffffffffffffffffffffffffffffffffffff90811682526001840154811660208084019190915260028501549182168385015260ff7401000000000000000000000000000000000000000090920482161515606080850191909152845160e08082018752600388015480861615158352610100808204871615159584019590955262010000810486161515978301979097526301000000870485161515928201929092526401000000009095049092161515608085810191909152600486015460a080870191909152600587015460c08088019190915291850195909552600686015494840194909452600785015493830193909352600884015490820152600983015491810191909152600a909101546101208201529050949350505050565b6000611f0b612285565b611f38600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b6001611f463387878761230b565b6006811115611f5757611f57613c79565b14611fbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f736574426f6e643a20526571756573746564000000000000000000000000000060448201526064016105ae565b6000611fcc3387878761276e565b60048101849055600a810154909150611fe6908490612d96565b9150506111a2600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b60606120398383612f84565b90505b92915050565b6000611be333878787878761176f565b600061205c612285565b610d218585858561230b565b6000612072612285565b60006120808686868661230b565b9050600681600681111561209657612096613c79565b14806120b3575060058160068111156120b1576120b1613c79565b145b80611be3575060038160068111156120cd576120cd613c79565b149695505050505050565b6120e0612285565b61210d600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b600161211b3388888861230b565b600681111561212c5761212c613c79565b14612193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f73657443616c6c6261636b733a2052657175657374656400000000000000000060448201526064016105ae565b60006121a13388888861276e565b60030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff1662010000861515027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff1617630100000085151502177fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff16640100000000841515021790555060018054740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909116179055505050505050565b6000610d2133868686866111aa565b60015474010000000000000000000000000000000000000000900460ff16612309576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105ae565b565b60008061231a8686868661276e565b600281015490915073ffffffffffffffffffffffffffffffffffffffff166123465760009150506111a2565b805473ffffffffffffffffffffffffffffffffffffffff1661236c5760019150506111a2565b600281015474010000000000000000000000000000000000000000900460ff161561239b5760069150506111a2565b600181015473ffffffffffffffffffffffffffffffffffffffff166123df576123c2610f15565b816008015411156123d45760026123d7565b60035b9150506111a2565b6123e7612ec2565b73ffffffffffffffffffffffffffffffffffffffff1663b551cd508661240d8488612f39565b612417878b612f84565b6040518463ffffffff1660e01b815260040161243593929190613e78565b60206040518083038186803b15801561244d57600080fd5b505afa158015612461573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124859190613d80565b612490576004611be3565b50600595945050505050565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4964656e74696669657257686974656c69737400000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e40906024015b60206040518083038186803b15801561252757600080fd5b505afa15801561253b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613f1a565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f436f6c6c61746572616c57686974656c69737400000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e409060240161250f565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f53746f7265000000000000000000000000000000000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e409060240161250f565b6000848484846040516020016126669493929190613f37565b604051602081830303815290604052805190602001209050949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff8085166024830152831660448201526064810182905261103d9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261301c565b60006120398284613f90565b600080600061277f8787878761264d565b81526020019081526020016000209050949350505050565b60015460009073ffffffffffffffffffffffffffffffffffffffff161561285857600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561282057600080fd5b505afa158015612834573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613fcd565b504290565b63bb74480081106128ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4c6976656e65737320746f6f206c61726765000000000000000000000000000060448201526064016105ae565b60008111612934576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4c6976656e6573732063616e6e6f74206265203000000000000000000000000060448201526064016105ae565b50565b6000806129468686868661230b565b905060006129568787878761276e565b6002810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055905060038260068111156129ad576129ad613c79565b1415612a0e57600681015460078201556009810154600a82015460048301546129db92916119b99190612d96565b81546002830154919450612a099173ffffffffffffffffffffffffffffffffffffffff908116911685612fc6565b612bec565b6005826006811115612a2257612a22613c79565b1415612b8a57612a30612ec2565b73ffffffffffffffffffffffffffffffffffffffff1663719c6d5687612a568489612f39565b612a60888c612f84565b6040518463ffffffff1660e01b8152600401612a7e93929190613e78565b60206040518083038186803b158015612a9657600080fd5b505afa158015612aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ace9190613fcd565b6007820181905560068201546004830154911415906000612af8612af185612da2565b8390613128565b9050612b1d84600901546119b986600a01546119b98587612d9690919063ffffffff16565b9550612b8283612b4457845473ffffffffffffffffffffffffffffffffffffffff16612b60565b600185015473ffffffffffffffffffffffffffffffffffffffff165b600286015473ffffffffffffffffffffffffffffffffffffffff169088612fc6565b505050612bec565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5f736574746c653a206e6f7420736574746c6561626c6500000000000000000060448201526064016105ae565b60018101548154600783015460405173ffffffffffffffffffffffffffffffffffffffff93841693928316928b16917f3f384afb4bd9f0aef0298c80399950011420eb33b0e1a750b20966270247b9a091612c4e918c918c918c918c90613fe6565b60405180910390a4612c9a600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055565b73ffffffffffffffffffffffffffffffffffffffff87163b15158015612ccc57506003810154640100000000900460ff165b15612d5f5760078101546040517f04cc1fd500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8916916304cc1fd591612d2c918a918a918a91600401613e97565b600060405180830381600087803b158015612d4657600080fd5b505af1158015612d5a573d6000803e3d6000fd5b505050505b612d8c600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055565b5050949350505050565b60006120398284614019565b600481015460009061203c906002613134565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015612e2757600080fd5b505afa158015612e3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e5f9190613fcd565b612e699190614019565b60405173ffffffffffffffffffffffffffffffffffffffff851660248201526044810182905290915061103d9085907f095ea7b300000000000000000000000000000000000000000000000000000000906064016126e0565b6002546040517faafd5e400000000000000000000000000000000000000000000000000000000081527f4f7261636c650000000000000000000000000000000000000000000000000000600482015260009173ffffffffffffffffffffffffffffffffffffffff169063aafd5e409060240161250f565b600382015460009060ff1615612f7d576005830154600090612f5d57600354612f63565b60058401545b6008850154909150612f759082613128565b91505061203c565b508061203c565b6060612039836040518060400160405280600b81526020017f6f6f52657175657374657200000000000000000000000000000000000000000081525084613140565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610e679084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016126e0565b600061307e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166131869092919063ffffffff16565b805190915015610e67578080602001905181019061309c9190613d80565b610e67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016105ae565b60006120398284613dcc565b60006120398284614060565b6060600061314e8585613195565b9050848161315b856131d7565b60405160200161316d9392919061409b565b6040516020818303038152906040529150509392505050565b60606111a28484600085613265565b8151606090156131c657816040516020016131b091906140de565b604051602081830303815290604052905061203c565b816040516020016131b0919061414a565b60606131f86fffffffffffffffffffffffffffffffff602084901c166133e5565b6132138360601b6bffffffffffffffffffffffff19166133e5565b60405160200161324f9291909182527fffffffffffffffff00000000000000000000000000000000000000000000000016602082015260280190565b6040516020818303038152906040529050919050565b6060824710156132f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016105ae565b843b61335f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ae565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613388919061418b565b60006040518083038185875af1925050503d80600081146133c5576040519150601f19603f3d011682016040523d82523d6000602084013e6133ca565b606091505b50915091506133da828286613587565b979650505050505050565b6000808260001c9050806fffffffffffffffffffffffffffffffff169050806801000000000000000002811777ffffffffffffffff0000000000000000ffffffffffffffff169050806401000000000281177bffffffff00000000ffffffff00000000ffffffff00000000ffffffff16905080620100000281177dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff169050806101000281177eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff1690508060100281177f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16905060006008827f0808080808080808080808080808080808080808080808080808080808080808168161350957613509614031565b0460047f040404040404040404040404040404040404040404040404040404040404040484160460027f020202020202020202020202020202020202020202020202020202020202020285160417166027029091017f3030303030303030303030303030303030303030303030303030303030303030019392505050565b60608315613596575081611112565b8251156135a65782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ae9190613bfb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261361a57600080fd5b813567ffffffffffffffff80821115613635576136356135da565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561367b5761367b6135da565b8160405283815286602085880101111561369457600080fd5b836020870160208301376000602085830101528094505050505092915050565b73ffffffffffffffffffffffffffffffffffffffff8116811461293457600080fd5b600080600080600060a086880312156136ee57600080fd5b8535945060208601359350604086013567ffffffffffffffff81111561371357600080fd5b61371f88828901613609565b9350506060860135613730816136b4565b949793965091946080013592915050565b60008060006060848603121561375657600080fd5b8335925060208401359150604084013567ffffffffffffffff81111561377b57600080fd5b61378786828701613609565b9150509250925092565b6000602082840312156137a357600080fd5b5035919050565b600080600080608085870312156137c057600080fd5b8435935060208501359250604085013567ffffffffffffffff8111156137e557600080fd5b6137f187828801613609565b949793965093946060013593505050565b6000806000806080858703121561381857600080fd5b8435613823816136b4565b93506020850135925060408501359150606085013567ffffffffffffffff81111561384d57600080fd5b61385987828801613609565b91505092959194509250565b600080600080600060a0868803121561387d57600080fd5b8535613888816136b4565b94506020860135613898816136b4565b93506040860135925060608601359150608086013567ffffffffffffffff8111156138c257600080fd5b6138ce88828901613609565b9150509295509295909350565b60008060008060008060c087890312156138f457600080fd5b86356138ff816136b4565b9550602087013561390f816136b4565b94506040870135935060608701359250608087013567ffffffffffffffff81111561393957600080fd5b61394589828a01613609565b92505060a087013590509295509295509295565b73ffffffffffffffffffffffffffffffffffffffff8b811682528a8116602083015289166040820152871515606082015261020081016139e5608083018980511515825260208101511515602083015260408101511515604083015260608101511515606083015260808101511515608083015260a081015160a083015260c081015160c08301525050565b6101608201969096526101808101949094526101a08401929092526101c08301526101e09091015295945050505050565b815173ffffffffffffffffffffffffffffffffffffffff16815261020081016020830151613a5c602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151613a84604084018273ffffffffffffffffffffffffffffffffffffffff169052565b506060830151613a98606084018215159052565b506080830151613af4608084018280511515825260208101511515602083015260408101511515604083015260608101511515606083015260808101511515608083015260a081015160a083015260c081015160c08301525050565b5060a083015161016083015260c083015161018083015260e08301516101a08301526101008301516101c0830152610120909201516101e09091015290565b60008060408385031215613b4657600080fd5b823567ffffffffffffffff811115613b5d57600080fd5b613b6985828601613609565b9250506020830135613b7a816136b4565b809150509250929050565b60005b83811015613ba0578181015183820152602001613b88565b8381111561103d5750506000910152565b60008151808452613bc9816020860160208601613b85565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006120396020830184613bb1565b600080600080600060a08688031215613c2657600080fd5b8535613c31816136b4565b94506020860135935060408601359250606086013567ffffffffffffffff811115613c5b57600080fd5b613c6788828901613609565b95989497509295608001359392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160078310613ce3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b801515811461293457600080fd5b60008060008060008060c08789031215613d1057600080fd5b8635955060208701359450604087013567ffffffffffffffff811115613d3557600080fd5b613d4189828a01613609565b9450506060870135613d5281613ce9565b92506080870135613d6281613ce9565b915060a0870135613d7281613ce9565b809150509295509295509295565b600060208284031215613d9257600080fd5b815161111281613ce9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613dde57613dde613d9d565b500390565b600060208284031215613df557600080fd5b6040516020810181811067ffffffffffffffff82111715613e1857613e186135da565b6040529151825250919050565b86815285602082015260c060408201526000613e4460c0830187613bb1565b73ffffffffffffffffffffffffffffffffffffffff95909516606083015250608081019290925260a0909101529392505050565b838152826020820152606060408201526000610d216060830184613bb1565b848152836020820152608060408201526000613eb66080830185613bb1565b905082606083015295945050505050565b86815285602082015260c060408201526000613ee660c0830187613bb1565b606083019590955250608081019290925273ffffffffffffffffffffffffffffffffffffffff1660a0909101529392505050565b600060208284031215613f2c57600080fd5b8151611112816136b4565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008560601b16815283601482015282603482015260008251613f80816054850160208701613b85565b9190910160540195945050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613fc857613fc8613d9d565b500290565b600060208284031215613fdf57600080fd5b5051919050565b85815284602082015260a06040820152600061400560a0830186613bb1565b606083019490945250608001529392505050565b6000821982111561402c5761402c613d9d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614096577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600084516140ad818460208901613b85565b8451908301906140c1818360208901613b85565b84519101906140d4818360208801613b85565b0195945050505050565b7f2c00000000000000000000000000000000000000000000000000000000000000815260008251614116816001850160208701613b85565b7f3a000000000000000000000000000000000000000000000000000000000000006001939091019283015250600201919050565b6000825161415c818460208701613b85565b7f3a00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b6000825161419d818460208701613b85565b919091019291505056fea264697066735822122076d9eb32bfdac668f344370ae32c96fb5078d448618c354883822990883f26cb64736f6c63430008090033" 5 | } 6 | } -------------------------------------------------------------------------------- /artifacts/Store.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi": [{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"_fixedOracleFeePerSecondPerPfc","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"_weeklyDelayFeePerSecondPerPfc","type":"tuple"},{"internalType":"address","name":"_timerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"newMember","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"AddedSharedMember","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"indexed":false,"internalType":"struct FixedPoint.Unsigned","name":"newFinalFee","type":"tuple"}],"name":"NewFinalFee","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"indexed":false,"internalType":"struct FixedPoint.Unsigned","name":"newOracleFee","type":"tuple"}],"name":"NewFixedOracleFeePerSecondPerPfc","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"indexed":false,"internalType":"struct FixedPoint.Unsigned","name":"newWeeklyDelayFeePerSecondPerPfc","type":"tuple"}],"name":"NewWeeklyDelayFeePerSecondPerPfc","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"oldMember","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"RemovedSharedMember","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roleId","type":"uint256"},{"indexed":true,"internalType":"address","name":"newMember","type":"address"},{"indexed":true,"internalType":"address","name":"manager","type":"address"}],"name":"ResetExclusiveMember","type":"event"},{"inputs":[],"name":"SECONDS_PER_WEEK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"newMember","type":"address"}],"name":"addMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"}],"name":"computeFinalFee","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"pfc","type":"tuple"}],"name":"computeRegularFee","outputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"regularFee","type":"tuple"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"latePenalty","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"finalFees","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedOracleFeePerSecondPerPfc","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"}],"name":"getMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"memberToCheck","type":"address"}],"name":"holdsRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payOracleFees","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Address","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"amount","type":"tuple"}],"name":"payOracleFeesErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"memberToRemove","type":"address"}],"name":"removeMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"}],"name":"renounceMembership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roleId","type":"uint256"},{"internalType":"address","name":"newMember","type":"address"}],"name":"resetMember","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"setCurrentTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"newFinalFee","type":"tuple"}],"name":"setFinalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"newFixedOracleFeePerSecondPerPfc","type":"tuple"}],"name":"setFixedOracleFeePerSecondPerPfc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"internalType":"struct FixedPoint.Unsigned","name":"newWeeklyDelayFeePerSecondPerPfc","type":"tuple"}],"name":"setWeeklyDelayFeePerSecondPerPfc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weeklyDelayFeePerSecondPerPfc","outputs":[{"internalType":"uint256","name":"rawValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20Address","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawErc20","outputs":[],"stateMutability":"nonpayable","type":"function"}], 3 | "bytecode": { 4 | "object": "0x60806040523480156200001157600080fd5b506040516200406238038062004062833981810160405281019062000037919062000ad0565b8080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200010160006001811115620000b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006001811115620000f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b33620001b260201b60201c565b620001876001808111156200013f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060018111156200017a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b33620003ff60201b60201c565b62000198836200041e60201b60201c565b620001a9826200055660201b60201c565b505050620010b4565b8260006002811115620001ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff1660028111156200024a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b146200028d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002849062000cee565b60405180910390fd5b6000806000868152602001908152602001600020905060018160010160006101000a81548160ff02191690836002811115620002f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b02179055508381600001819055506200031d83826002016200068f60201b620017681790919060201c565b6000600281111562000358577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008086815260200190815260200160002060010160009054906101000a900460ff166002811115620003b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415620003f8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003ef9062000ccc565b60405180910390fd5b5050505050565b8260018190555062000419838383620001b260201b60201c565b505050565b6000600181111562000459577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6200046b8133620006a560201b60201c565b620004ad576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620004a49062000caa565b60405180910390fd5b620004c86001836200086460201b620017761790919060201c565b6200050a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005019062000c66565b60405180910390fd5b816003600082015181600001559050507e41cf46cedaae9927def5c0647b190fd958c8ab8cde4219dad74319bc05d3d9826040516200054a919062000d54565b60405180910390a15050565b6000600181111562000591577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b620005a38133620006a560201b60201c565b620005e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620005dc9062000caa565b60405180910390fd5b620006006001836200086460201b620017761790919060201c565b62000642576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620006399062000c88565b60405180910390fd5b816004600082015181600001559050507f2e6cd3e6f7808568620c647ac0e652b0e95bef2494692adbc118fbbd02a8e82e8260405162000683919062000d54565b60405180910390a15050565b620006a182826200088960201b60201c565b5050565b600080600080858152602001908152602001600020905060016002811115620006f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160010160009054906101000a900460ff16600281111562000742577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156200076f576200076683826002016200094360201b620017931790919060201c565b9150506200085e565b600280811115620007a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160010160009054906101000a900460ff166002811115620007f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156200082157620008188382600301620009a060201b620017f01790919060201c565b9150506200085e565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008559062000d32565b60405180910390fd5b92915050565b60006200087782620009f960201b60201c565b60000151836000015110905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620008fc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008f39062000d10565b60405180910390fd5b808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60008173ffffffffffffffffffffffffffffffffffffffff168360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b62000a0362000a52565b604051806020016040528062000a30670de0b6b3a76400008562000a3a60201b620018491790919060201c565b8152509050919050565b6000818362000a4a919062000dab565b905092915050565b6040518060200160405280600081525090565b60008151905062000a768162001080565b92915050565b60006020828403121562000a8f57600080fd5b62000a9b602062000d71565b9050600062000aad8482850162000ab9565b60008301525092915050565b60008151905062000aca816200109a565b92915050565b60008060006060848603121562000ae657600080fd5b600062000af68682870162000a7c565b935050602062000b098682870162000a7c565b925050604062000b1c8682870162000a65565b9150509250925092565b600062000b35601e8362000d9a565b915062000b428262000eef565b602082019050919050565b600062000b5c601f8362000d9a565b915062000b698262000f18565b602082019050919050565b600062000b8360228362000d9a565b915062000b908262000f41565b604082019050919050565b600062000baa603c8362000d9a565b915062000bb78262000f90565b604082019050919050565b600062000bd1601e8362000d9a565b915062000bde8262000fdf565b602082019050919050565b600062000bf860238362000d9a565b915062000c058262001008565b604082019050919050565b600062000c1f600e8362000d9a565b915062000c2c8262001057565b602082019050919050565b60208201600082015162000c4f600085018262000c55565b50505050565b62000c608162000e40565b82525050565b6000602082019050818103600083015262000c818162000b26565b9050919050565b6000602082019050818103600083015262000ca38162000b4d565b9050919050565b6000602082019050818103600083015262000cc58162000b74565b9050919050565b6000602082019050818103600083015262000ce78162000b9b565b9050919050565b6000602082019050818103600083015262000d098162000bc2565b9050919050565b6000602082019050818103600083015262000d2b8162000be9565b9050919050565b6000602082019050818103600083015262000d4d8162000c10565b9050919050565b600060208201905062000d6b600083018462000c37565b92915050565b600062000d7d62000d90565b905062000d8b828262000e4a565b919050565b6000604051905090565b600082825260208201905092915050565b600062000db88262000e40565b915062000dc58362000e40565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161562000e015762000e0062000e80565b5b828202905092915050565b600062000e198262000e20565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b62000e558262000ede565b810181811067ffffffffffffffff8211171562000e775762000e7662000eaf565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f466565206d757374206265203c203130302520706572207365636f6e642e0000600082015250565b7f7765656b6c792064656c617920666565206d757374206265203c203130302500600082015250565b7f53656e64657220646f6573206e6f7420686f6c6420726571756972656420726f60008201527f6c65000000000000000000000000000000000000000000000000000000000000602082015250565b7f417474656d7074656420746f2075736520616e20696e76616c696420726f6c6560008201527f20746f206d616e61676520616e206578636c757369766520726f6c6500000000602082015250565b7f43616e6e6f74207573652061207072652d6578697374696e6720726f6c650000600082015250565b7f43616e6e6f742073657420616e206578636c757369766520726f6c6520746f2060008201527f3078300000000000000000000000000000000000000000000000000000000000602082015250565b7f496e76616c696420726f6c654964000000000000000000000000000000000000600082015250565b6200108b8162000e0c565b81146200109757600080fd5b50565b620010a58162000e40565b8114620010b157600080fd5b50565b612f9e80620010c46000396000f3fe6080604052600436106101355760003560e01c80637d69dfdb116100ab578063ab3545e51161006f578063ab3545e514610425578063acb6f6cb14610462578063b187487d1461048b578063bd1f4b52146104b4578063cd3a9b24146104dd578063d97c05be146104e757610135565b80637d69dfdb146103545780637e7e591d1461037f57806384ae2a74146103a85780638659d232146103d3578063aaa14ca3146103fc57610135565b80635b97aadd116100fd5780635b97aadd1461020d5780636be7658b1461024a5780636f356f4a1461027357806374201feb146102b057806374d0a676146102ee5780637cdc1cb91461031757610135565b80631c39c38d1461013a57806322f8e5661461016557806329cb924d1461018e5780632e1a7d4d146101b95780632fee2098146101e2575b600080fd5b34801561014657600080fd5b5061014f610510565b60405161015c91906125e9565b60405180910390f35b34801561017157600080fd5b5061018c600480360381019061018791906121cb565b610536565b005b34801561019a57600080fd5b506101a3610622565b6040516101b091906128e5565b60405180910390f35b3480156101c557600080fd5b506101e060048036038101906101db91906121cb565b610727565b005b3480156101ee57600080fd5b506101f7610781565b60405161020491906128e5565b60405180910390f35b34801561021957600080fd5b50610234600480360381019061022f919061209c565b61078d565b60405161024191906128a1565b60405180910390f35b34801561025657600080fd5b50610271600480360381019061026c919061221d565b6107f0565b005b34801561027f57600080fd5b5061029a6004803603810190610295919061209c565b6109ac565b6040516102a791906128e5565b60405180910390f35b3480156102bc57600080fd5b506102d760048036038101906102d29190612259565b6109ca565b6040516102e59291906128bc565b60405180910390f35b3480156102fa57600080fd5b506103156004803603810190610310919061221d565b610ae0565b005b34801561032357600080fd5b5061033e6004803603810190610339919061221d565b610c9c565b60405161034b9190612664565b60405180910390f35b34801561036057600080fd5b50610369610e43565b60405161037691906128e5565b60405180910390f35b34801561038b57600080fd5b506103a660048036038101906103a19190612101565b610e4f565b005b3480156103b457600080fd5b506103bd610f5b565b6040516103ca91906128e5565b60405180910390f35b3480156103df57600080fd5b506103fa60048036038101906103f591906120c5565b610f62565b005b34801561040857600080fd5b50610423600480360381019061041e91906121cb565b611000565b005b34801561043157600080fd5b5061044c600480360381019061044791906121cb565b6111a6565b60405161045991906125e9565b60405180910390f35b34801561046e57600080fd5b50610489600480360381019061048491906121a2565b6112a3565b005b34801561049757600080fd5b506104b260048036038101906104ad91906121a2565b6113c3565b005b3480156104c057600080fd5b506104db60048036038101906104d6919061213d565b6114e4565b005b6104e5611566565b005b3480156104f357600080fd5b5061050e6004803603810190610509919061221d565b6115ab565b005b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600073ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561059257600080fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166322f8e566826040518263ffffffff1660e01b81526004016105ed91906128e5565b600060405180830381600087803b15801561060757600080fd5b505af115801561061b573d6000803e3d6000fd5b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461072057600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166329cb924d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156106e157600080fd5b505afa1580156106f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071991906121f4565b9050610724565b4290505b90565b6001546107348133610c9c565b610773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161076a906127a1565b60405180910390fd5b61077d338361185f565b5050565b60038060000154905081565b610795611fe2565b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060200160405290816000820154815250509050919050565b8160028081111561082a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff166002811115610885577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b146108c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108bc90612781565b60405180910390fd5b826108e56000808381526020019081526020016000206000015433610c9c565b610924576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091b90612801565b60405180910390fd5b61094b8360008087815260200190815260200160002060030161195390919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857feb3e33034c392e69263b04ec0fa376dc12784a41b6676c7f31b936cbc0fbb5af60405160405180910390a450505050565b60056020528060005260406000206000915090508060000154905081565b6109d2611fe2565b6109da611fe2565b60006109ef86866119b190919063ffffffff16565b9050610a3c6003604051806020016040529081600082015481525050610a2e8387803603810190610a2091906121a2565b6119c790919063ffffffff16565b6119fc90919063ffffffff16565b92506000610a5a87610a4c610622565b6119b190919063ffffffff16565b90506000610a9c610a7762093a8084611a4890919063ffffffff16565b60046040518060200160405290816000820154815250506119c790919063ffffffff16565b9050610ad381610ac58589803603810190610ab791906121a2565b6119c790919063ffffffff16565b6119fc90919063ffffffff16565b9350505050935093915050565b81600280811115610b1a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff166002811115610b75577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14610bb5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bac90612781565b60405180910390fd5b82610bd56000808381526020019081526020016000206000015433610c9c565b610c14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c0b90612801565b60405180910390fd5b610c3b83600080878152602001908152602001600020600301611a5e90919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f63502af7324ff6db91ab38f8236a648727d9385ea6c782073dd4882d8a61a48f60405160405180910390a450505050565b600080600080858152602001908152602001600020905060016002811115610ced577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160010160009054906101000a900460ff166002811115610d37577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610d5b57610d53838260020161179390919063ffffffff16565b915050610e3d565b600280811115610d94577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8160010160009054906101000a900460ff166002811115610dde577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415610e0257610dfa83826003016117f090919063ffffffff16565b915050610e3d565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3490612821565b60405180910390fd5b92915050565b60048060000154905081565b60006001811115610e89577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b610e938133610c9c565b610ed2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec9906127a1565b60405180910390fd5b81600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001559050507f98c807f575ae6584ff8200eaf3205f3f20abf9c954fff030c152f5e7c5446d6e82604051610f4e91906128a1565b60405180910390a1505050565b62093a8081565b6000829050610f8b600083803603810190610f7d91906121a2565b611b2c90919063ffffffff16565b610fca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fc190612861565b60405180910390fd5b610ffb333084600001358473ffffffffffffffffffffffffffffffffffffffff16611b49909392919063ffffffff16565b505050565b8060028081111561103a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff166002811115611095577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b146110d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110cc90612781565b60405180910390fd5b816110e08133610c9c565b61111f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611116906127a1565b60405180910390fd5b6111463360008086815260200190815260200160002060030161195390919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16847feb3e33034c392e69263b04ec0fa376dc12784a41b6676c7f31b936cbc0fbb5af60405160405180910390a4505050565b600081600160028111156111e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff16600281111561123e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590612701565b60405180910390fd5b61129b600080858152602001908152602001600020600201611bd2565b915050919050565b600060018111156112dd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6112e78133610c9c565b611326576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131d906127a1565b60405180910390fd5b61133a60018361177690919063ffffffff16565b611379576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611370906126c1565b60405180910390fd5b816003600082015181600001559050507e41cf46cedaae9927def5c0647b190fd958c8ab8cde4219dad74319bc05d3d9826040516113b791906128a1565b60405180910390a15050565b600060018111156113fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6114078133610c9c565b611446576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161143d906127a1565b60405180910390fd5b61145a60018361177690919063ffffffff16565b611499576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611490906126e1565b60405180910390fd5b816004600082015181600001559050507f2e6cd3e6f7808568620c647ac0e652b0e95bef2494692adbc118fbbd02a8e82e826040516114d891906128a1565b60405180910390a15050565b6001546114f18133610c9c565b611530576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611527906127a1565b60405180910390fd5b600083905061156033848373ffffffffffffffffffffffffffffffffffffffff16611c009092919063ffffffff16565b50505050565b600034116115a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115a090612881565b60405180910390fd5b565b81600160028111156115e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008083815260200190815260200160002060010160009054906101000a900460ff166002811115611641577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161167890612701565b60405180910390fd5b826116a16000808381526020019081526020016000206000015433610c9c565b6116e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d790612801565b60405180910390fd5b61170783600080878152602001908152602001600020600201611c8690919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f3b855c56b409b671c7112789d022675eb639d0bcb8896f1b6197c132f799e74660405160405180910390a450505050565b6117728282611c86565b5050565b600061178182611d3d565b60000151836000015110905092915050565b60008173ffffffffffffffffffffffffffffffffffffffff168360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614905092915050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600081836118579190612988565b905092915050565b804710156118a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189990612741565b60405180910390fd5b60008273ffffffffffffffffffffffffffffffffffffffff16826040516118c8906125d4565b60006040518083038185875af1925050503d8060008114611905576040519150601f19603f3d011682016040523d82523d6000602084013e61190a565b606091505b505090508061194e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161194590612721565b60405180910390fd5b505050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600081836119bf91906129e2565b905092915050565b6119cf611fe2565b60405180602001604052806119f184866000015161184990919063ffffffff16565b815250905092915050565b611a04611fe2565b6040518060200160405280670de0b6b3a7640000611a338560000151876000015161184990919063ffffffff16565b611a3d9190612957565b815250905092915050565b60008183611a569190612957565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ace576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac5906126a1565b60405180910390fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000611b3782611d3d565b60000151836000015111905092915050565b611bcc846323b872dd60e01b858585604051602401611b6a93929190612604565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d75565b50505050565b60008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611c818363a9059cbb60e01b8484604051602401611c1f92919061263b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d75565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cf6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ced906127c1565b60405180910390fd5b808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b611d45611fe2565b6040518060200160405280611d6b670de0b6b3a76400008561184990919063ffffffff16565b8152509050919050565b6000611dd7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611e3c9092919063ffffffff16565b9050600081511115611e375780806020019051810190611df79190612179565b611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90612841565b60405180910390fd5b5b505050565b6060611e4b8484600085611e54565b90509392505050565b606082471015611e99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9090612761565b60405180910390fd5b611ea285611f68565b611ee1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed8906127e1565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611f0a91906125bd565b60006040518083038185875af1925050503d8060008114611f47576040519150601f19603f3d011682016040523d82523d6000602084013e611f4c565b606091505b5091509150611f5c828286611f7b565b92505050949350505050565b600080823b905060008111915050919050565b60608315611f8b57829050611fdb565b600083511115611f9e5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd2919061267f565b60405180910390fd5b9392505050565b6040518060200160405280600081525090565b60008135905061200481612f23565b92915050565b60008151905061201981612f3a565b92915050565b60006020828403121561203157600080fd5b81905092915050565b60006020828403121561204c57600080fd5b6120566020612900565b9050600061206684828501612072565b60008301525092915050565b60008135905061208181612f51565b92915050565b60008151905061209681612f51565b92915050565b6000602082840312156120ae57600080fd5b60006120bc84828501611ff5565b91505092915050565b600080604083850312156120d857600080fd5b60006120e685828601611ff5565b92505060206120f78582860161201f565b9150509250929050565b6000806040838503121561211457600080fd5b600061212285828601611ff5565b92505060206121338582860161203a565b9150509250929050565b6000806040838503121561215057600080fd5b600061215e85828601611ff5565b925050602061216f85828601612072565b9150509250929050565b60006020828403121561218b57600080fd5b60006121998482850161200a565b91505092915050565b6000602082840312156121b457600080fd5b60006121c28482850161203a565b91505092915050565b6000602082840312156121dd57600080fd5b60006121eb84828501612072565b91505092915050565b60006020828403121561220657600080fd5b600061221484828501612087565b91505092915050565b6000806040838503121561223057600080fd5b600061223e85828601612072565b925050602061224f85828601611ff5565b9150509250929050565b60008060006060848603121561226e57600080fd5b600061227c86828701612072565b935050602061228d86828701612072565b925050604061229e8682870161201f565b9150509250925092565b6122b181612a16565b82525050565b6122c081612a28565b82525050565b60006122d182612925565b6122db818561293b565b93506122eb818560208601612a5e565b80840191505092915050565b600061230282612930565b61230c8185612946565b935061231c818560208601612a5e565b61232581612b4f565b840191505092915050565b600061233d601f83612946565b915061234882612b60565b602082019050919050565b6000612360601e83612946565b915061236b82612b89565b602082019050919050565b6000612383601f83612946565b915061238e82612bb2565b602082019050919050565b60006123a6602f83612946565b91506123b182612bdb565b604082019050919050565b60006123c9603a83612946565b91506123d482612c2a565b604082019050919050565b60006123ec601d83612946565b91506123f782612c79565b602082019050919050565b600061240f602683612946565b915061241a82612ca2565b604082019050919050565b6000612432602c83612946565b915061243d82612cf1565b604082019050919050565b6000612455602283612946565b915061246082612d40565b604082019050919050565b6000612478602383612946565b915061248382612d8f565b604082019050919050565b600061249b60008361293b565b91506124a682612dde565b600082019050919050565b60006124be601d83612946565b91506124c982612de1565b602082019050919050565b60006124e1602483612946565b91506124ec82612e0a565b604082019050919050565b6000612504600e83612946565b915061250f82612e59565b602082019050919050565b6000612527602a83612946565b915061253282612e82565b604082019050919050565b600061254a601983612946565b915061255582612ed1565b602082019050919050565b600061256d601883612946565b915061257882612efa565b602082019050919050565b602082016000820151612599600085018261259f565b50505050565b6125a881612a54565b82525050565b6125b781612a54565b82525050565b60006125c982846122c6565b915081905092915050565b60006125df8261248e565b9150819050919050565b60006020820190506125fe60008301846122a8565b92915050565b600060608201905061261960008301866122a8565b61262660208301856122a8565b61263360408301846125ae565b949350505050565b600060408201905061265060008301856122a8565b61265d60208301846125ae565b9392505050565b600060208201905061267960008301846122b7565b92915050565b6000602082019050818103600083015261269981846122f7565b905092915050565b600060208201905081810360008301526126ba81612330565b9050919050565b600060208201905081810360008301526126da81612353565b9050919050565b600060208201905081810360008301526126fa81612376565b9050919050565b6000602082019050818103600083015261271a81612399565b9050919050565b6000602082019050818103600083015261273a816123bc565b9050919050565b6000602082019050818103600083015261275a816123df565b9050919050565b6000602082019050818103600083015261277a81612402565b9050919050565b6000602082019050818103600083015261279a81612425565b9050919050565b600060208201905081810360008301526127ba81612448565b9050919050565b600060208201905081810360008301526127da8161246b565b9050919050565b600060208201905081810360008301526127fa816124b1565b9050919050565b6000602082019050818103600083015261281a816124d4565b9050919050565b6000602082019050818103600083015261283a816124f7565b9050919050565b6000602082019050818103600083015261285a8161251a565b9050919050565b6000602082019050818103600083015261287a8161253d565b9050919050565b6000602082019050818103600083015261289a81612560565b9050919050565b60006020820190506128b66000830184612583565b92915050565b60006040820190506128d16000830185612583565b6128de6020830184612583565b9392505050565b60006020820190506128fa60008301846125ae565b92915050565b600061290a61291b565b90506129168282612a91565b919050565b6000604051905090565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b600061296282612a54565b915061296d83612a54565b92508261297d5761297c612af1565b5b828204905092915050565b600061299382612a54565b915061299e83612a54565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156129d7576129d6612ac2565b5b828202905092915050565b60006129ed82612a54565b91506129f883612a54565b925082821015612a0b57612a0a612ac2565b5b828203905092915050565b6000612a2182612a34565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b83811015612a7c578082015181840152602081019050612a61565b83811115612a8b576000848401525b50505050565b612a9a82612b4f565b810181811067ffffffffffffffff82111715612ab957612ab8612b20565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f43616e6e6f74206164642030783020746f20612073686172656420726f6c6500600082015250565b7f466565206d757374206265203c203130302520706572207365636f6e642e0000600082015250565b7f7765656b6c792064656c617920666565206d757374206265203c203130302500600082015250565b7f4d7573742062652063616c6c6564206f6e20616e20696e697469616c697a656460008201527f204578636c757369766520726f6c650000000000000000000000000000000000602082015250565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260008201527f6563697069656e74206d61792068617665207265766572746564000000000000602082015250565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000600082015250565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b7f4d7573742062652063616c6c6564206f6e20616e20696e697469616c697a656460008201527f2053686172656420726f6c650000000000000000000000000000000000000000602082015250565b7f53656e64657220646f6573206e6f7420686f6c6420726571756972656420726f60008201527f6c65000000000000000000000000000000000000000000000000000000000000602082015250565b7f43616e6e6f742073657420616e206578636c757369766520726f6c6520746f2060008201527f3078300000000000000000000000000000000000000000000000000000000000602082015250565b50565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b7f43616e206f6e6c792062652063616c6c6564206279206120726f6c65206d616e60008201527f6167657200000000000000000000000000000000000000000000000000000000602082015250565b7f496e76616c696420726f6c654964000000000000000000000000000000000000600082015250565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b7f416d6f756e742073656e742063616e2774206265207a65726f00000000000000600082015250565b7f56616c75652073656e742063616e2774206265207a65726f0000000000000000600082015250565b612f2c81612a16565b8114612f3757600080fd5b50565b612f4381612a28565b8114612f4e57600080fd5b50565b612f5a81612a54565b8114612f6557600080fd5b5056fea2646970667358221220b63bb3d6304bdd842f677d98e29e09af5ab580acd960acceafa4a5ff96799ac164736f6c63430008040033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 5 | } 6 | } -------------------------------------------------------------------------------- /audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polymarket/uma-ctf-adapter/7f7dccd745023f908ae2c43717ae906b3d16872d/audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf -------------------------------------------------------------------------------- /deploy/scripts/deploy_adapter.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source .env 4 | 5 | echo "Deploying UmaCtfAdapter..." 6 | 7 | echo "Deploy args: 8 | ConditionalTokensFramework: $CTF 9 | Finder: $FINDER 10 | " 11 | 12 | OUTPUT="$(forge script Deploy \ 13 | --private-key $PK \ 14 | --rpc-url $RPC_URL \ 15 | --json \ 16 | --broadcast \ 17 | -s "deploy(address,address)" $CTF $FINDER)" 18 | 19 | ADAPTER=$(echo "$OUTPUT" | grep "{" | jq -r .returns.adapter.value) 20 | echo "Adapter deployed: $ADAPTER" 21 | 22 | echo "Complete!" 23 | -------------------------------------------------------------------------------- /docs/adapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polymarket/uma-ctf-adapter/7f7dccd745023f908ae2c43717ae906b3d16872d/docs/adapter.png -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | solc = "0.8.15" 3 | ffi = true 4 | fs_permissions = [{ access = "read", path = "./artifacts/"}] 5 | gas_reports = ["*"] 6 | out = "out" 7 | optimizer_runs = 1000000 8 | 9 | # fuzz settings 10 | [profile.default.fuzz] 11 | runs = 256 12 | [profile.intense.fuzz] 13 | runs = 10_000 14 | 15 | [fmt] 16 | line_length = 120 17 | tab_width = 4 18 | bracket_spacing = true 19 | single_line_statement_blocks = "single" -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@polymarket/uma-ctf-adapter", 3 | "description": "Contracts to resolve Polymarket prediction markets via UMA's Optimistic Oracle", 4 | "version": "3.0.0", 5 | "contributors": [ 6 | { 7 | "name": "Jonathan Amenechi", 8 | "url": "https://github.com/JonathanAmenechi" 9 | }, 10 | { 11 | "name": "Liam Kovatch", 12 | "url": "https://github.com/L-Kov" 13 | } 14 | ], 15 | "keywords": [ 16 | "blockchain", 17 | "ethereum", 18 | "hardhat", 19 | "smart-contracts", 20 | "solidity" 21 | ], 22 | "license": "MIT", 23 | "scripts": { 24 | "test": "forge test" 25 | }, 26 | "devDependencies": { 27 | "prettier": "^2.5.1", 28 | "prettier-plugin-solidity": "^1.0.0-beta.19" 29 | } 30 | } -------------------------------------------------------------------------------- /src/UmaCtfAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { IERC20 } from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | 6 | import { Auth } from "./mixins/Auth.sol"; 7 | import { BulletinBoard } from "./mixins/BulletinBoard.sol"; 8 | 9 | import { TransferHelper } from "./libraries/TransferHelper.sol"; 10 | import { PayoutHelperLib } from "./libraries/PayoutHelperLib.sol"; 11 | import { AncillaryDataLib } from "./libraries/AncillaryDataLib.sol"; 12 | 13 | import { IFinder } from "./interfaces/IFinder.sol"; 14 | import { IAddressWhitelist } from "./interfaces/IAddressWhitelist.sol"; 15 | import { IConditionalTokens } from "./interfaces/IConditionalTokens.sol"; 16 | import { IOptimisticOracleV2 } from "./interfaces/IOptimisticOracleV2.sol"; 17 | import { IOptimisticRequester } from "./interfaces/IOptimisticRequester.sol"; 18 | 19 | import { QuestionData, IUmaCtfAdapter } from "./interfaces/IUmaCtfAdapter.sol"; 20 | 21 | /// @title UmaCtfAdapter 22 | /// @notice Enables resolution of Polymarket CTF markets via UMA's Optimistic Oracle 23 | contract UmaCtfAdapter is IUmaCtfAdapter, Auth, BulletinBoard, IOptimisticRequester { 24 | /*/////////////////////////////////////////////////////////////////// 25 | IMMUTABLES 26 | //////////////////////////////////////////////////////////////////*/ 27 | 28 | /// @notice Conditional Tokens Framework 29 | IConditionalTokens public immutable ctf; 30 | 31 | /// @notice Optimistic Oracle 32 | IOptimisticOracleV2 public immutable optimisticOracle; 33 | 34 | /// @notice Collateral Whitelist 35 | IAddressWhitelist public immutable collateralWhitelist; 36 | 37 | /// @notice Time period after which an admin can emergency resolve a condition 38 | uint256 public constant EMERGENCY_SAFETY_PERIOD = 2 days; 39 | 40 | /// @notice Unique query identifier for the Optimistic Oracle 41 | /// From UMIP-107 42 | bytes32 public constant YES_OR_NO_IDENTIFIER = "YES_OR_NO_QUERY"; 43 | 44 | /// @notice Maximum ancillary data length 45 | /// From OOV2 function OO_ANCILLARY_DATA_LIMIT 46 | uint256 public constant MAX_ANCILLARY_DATA = 8139; 47 | 48 | /// @notice Mapping of questionID to QuestionData 49 | mapping(bytes32 => QuestionData) public questions; 50 | 51 | modifier onlyOptimisticOracle() { 52 | if (msg.sender != address(optimisticOracle)) revert NotOptimisticOracle(); 53 | _; 54 | } 55 | 56 | /// @param _ctf - The Conditional Token Framework Address 57 | /// - When deployed for negative risk markets, this should be the `NegRiskOperator` contract address 58 | /// @param _finder - The UMA Finder contract address 59 | constructor(address _ctf, address _finder) { 60 | ctf = IConditionalTokens(_ctf); 61 | IFinder finder = IFinder(_finder); 62 | optimisticOracle = IOptimisticOracleV2(finder.getImplementationAddress("OptimisticOracleV2")); 63 | collateralWhitelist = IAddressWhitelist(finder.getImplementationAddress("CollateralWhitelist")); 64 | } 65 | 66 | /*/////////////////////////////////////////////////////////////////// 67 | PUBLIC FUNCTIONS 68 | //////////////////////////////////////////////////////////////////*/ 69 | 70 | /// @notice Initializes a question 71 | /// Atomically adds the question to the Adapter, prepares it on the ConditionalTokens Framework and requests a price from the OO. 72 | /// If a reward is provided, the caller must have approved the Adapter as spender and have enough rewardToken 73 | /// to pay for the price request. 74 | /// Prepares the condition using the Adapter as the oracle and a fixed outcome slot count = 2. 75 | /// @param ancillaryData - Data used to resolve a question 76 | /// @param rewardToken - ERC20 token address used for payment of rewards and fees 77 | /// @param reward - Reward offered to a successful OO proposer. 78 | /// Must be chosen carefully, to properly economically incentize OO proposers. 79 | /// @param proposalBond - Bond required to be posted by OO proposers/disputers. 80 | /// If 0, the default OO bond is used. 81 | /// Must be chosen carefully, to properly economically incentize OO proposers and disputers. 82 | /// Questions expected to secure a large amount of value should consider a larger proposal bond. 83 | /// @param liveness - OO liveness period in seconds. 84 | /// If 0, the default liveness period of 2 hours is used. 85 | /// Must be chosen carefully, depending on the value backed by the question. 86 | /// Questions expected to secure a large amount of value should consider a longer liveness period. 87 | function initialize( 88 | bytes memory ancillaryData, 89 | address rewardToken, 90 | uint256 reward, 91 | uint256 proposalBond, 92 | uint256 liveness 93 | ) external returns (bytes32 questionID) { 94 | if (!collateralWhitelist.isOnWhitelist(rewardToken)) revert UnsupportedToken(); 95 | 96 | bytes memory data = AncillaryDataLib._appendAncillaryData(msg.sender, ancillaryData); 97 | if (ancillaryData.length == 0 || data.length > MAX_ANCILLARY_DATA) revert InvalidAncillaryData(); 98 | 99 | questionID = keccak256(data); 100 | 101 | if (_isInitialized(questions[questionID])) revert Initialized(); 102 | 103 | uint256 timestamp = block.timestamp; 104 | 105 | // Persist the question parameters in storage 106 | _saveQuestion(msg.sender, questionID, data, timestamp, rewardToken, reward, proposalBond, liveness); 107 | 108 | // Prepare the question on the CTF 109 | ctf.prepareCondition(address(this), questionID, 2); 110 | 111 | // Request a price for the question from the OO 112 | _requestPrice(msg.sender, timestamp, data, rewardToken, reward, proposalBond, liveness); 113 | 114 | emit QuestionInitialized(questionID, timestamp, msg.sender, data, rewardToken, reward, proposalBond); 115 | } 116 | 117 | /// @notice Checks whether a questionID is ready to be resolved 118 | /// @param questionID - The unique questionID 119 | function ready(bytes32 questionID) public view returns (bool) { 120 | return _ready(questions[questionID]); 121 | } 122 | 123 | /// @notice Resolves a question 124 | /// Pulls price information from the OO and resolves the underlying CTF market. 125 | /// Reverts if price is not available on the OO 126 | /// Resets the question if the price returned by the OO is the Ignore price 127 | /// @param questionID - The unique questionID of the question 128 | function resolve(bytes32 questionID) external { 129 | QuestionData storage questionData = questions[questionID]; 130 | 131 | if (!_isInitialized(questionData)) revert NotInitialized(); 132 | if (questionData.paused) revert Paused(); 133 | if (questionData.resolved) revert Resolved(); 134 | if (!_hasPrice(questionData)) revert NotReadyToResolve(); 135 | 136 | // Resolve the underlying market 137 | return _resolve(questionID, questionData); 138 | } 139 | 140 | /// @notice Retrieves the expected payout array of the question 141 | /// @param questionID - The unique questionID of the question 142 | function getExpectedPayouts(bytes32 questionID) public view returns (uint256[] memory) { 143 | QuestionData storage questionData = questions[questionID]; 144 | 145 | if (!_isInitialized(questionData)) revert NotInitialized(); 146 | if (_isFlagged(questionData)) revert Flagged(); 147 | if (questionData.paused) revert Paused(); 148 | 149 | if (!_hasPrice(questionData)) revert PriceNotAvailable(); 150 | 151 | // Fetches price from OO 152 | int256 price = optimisticOracle.getRequest( 153 | address(this), YES_OR_NO_IDENTIFIER, questionData.requestTimestamp, questionData.ancillaryData 154 | ).resolvedPrice; 155 | 156 | return _constructPayouts(price); 157 | } 158 | 159 | /// @notice Callback which is executed on dispute 160 | /// Resets the question and sends out a new price request to the OO 161 | /// @param ancillaryData - Ancillary data of the request 162 | function priceDisputed(bytes32, uint256, bytes memory ancillaryData, uint256) external onlyOptimisticOracle { 163 | bytes32 questionID = keccak256(ancillaryData); 164 | QuestionData storage questionData = questions[questionID]; 165 | 166 | // If a Question is already resolved, e.g by emergencyResolve, the priceDisputed callback should not update 167 | // any storage parameters. 168 | // Refund the reward to the question creator 169 | if (questionData.resolved) { 170 | TransferHelper._transfer(questionData.rewardToken, questionData.creator, questionData.reward); 171 | return; 172 | } 173 | 174 | if (questionData.reset) { 175 | questionData.refund = true; 176 | return; 177 | } 178 | 179 | // If the question has not been reset previously, reset the question 180 | // Ensures that there are at most 2 OO Requests at a time for a question 181 | _reset(address(this), questionID, false, questionData); 182 | } 183 | 184 | /// @notice Checks if a question is initialized 185 | /// @param questionID - The unique questionID 186 | function isInitialized(bytes32 questionID) public view returns (bool) { 187 | return _isInitialized(questions[questionID]); 188 | } 189 | 190 | /// @notice Checks if a question has been flagged for emergency resolution 191 | /// @param questionID - The unique questionID 192 | function isFlagged(bytes32 questionID) public view returns (bool) { 193 | return _isFlagged(questions[questionID]); 194 | } 195 | 196 | /// @notice Gets the QuestionData for the given questionID 197 | /// @param questionID - The unique questionID 198 | function getQuestion(bytes32 questionID) external view returns (QuestionData memory) { 199 | return questions[questionID]; 200 | } 201 | 202 | /*//////////////////////////////////////////////////////////////////// 203 | ADMIN ONLY FUNCTIONS 204 | ///////////////////////////////////////////////////////////////////*/ 205 | 206 | /// @notice Flags a market for emergency resolution 207 | /// @param questionID - The unique questionID of the question 208 | function flag(bytes32 questionID) external onlyAdmin { 209 | QuestionData storage questionData = questions[questionID]; 210 | 211 | if (!_isInitialized(questionData)) revert NotInitialized(); 212 | if (_isFlagged(questionData)) revert Flagged(); 213 | if (questionData.resolved) revert Resolved(); 214 | 215 | questionData.emergencyResolutionTimestamp = block.timestamp + EMERGENCY_SAFETY_PERIOD; 216 | questionData.paused = true; 217 | 218 | emit QuestionFlagged(questionID); 219 | } 220 | 221 | /// @notice Unflags a market for emergency resolution 222 | /// @param questionID - The unique questionID of the question 223 | function unflag(bytes32 questionID) external onlyAdmin { 224 | QuestionData storage questionData = questions[questionID]; 225 | 226 | if (!_isInitialized(questionData)) revert NotInitialized(); 227 | if (!_isFlagged(questionData)) revert NotFlagged(); 228 | if (questionData.resolved) revert Resolved(); 229 | if (block.timestamp > questionData.emergencyResolutionTimestamp) revert SafetyPeriodPassed(); 230 | 231 | questionData.emergencyResolutionTimestamp = 0; 232 | questionData.paused = false; 233 | 234 | emit QuestionUnflagged(questionID); 235 | } 236 | 237 | /// @notice Allows an admin to reset a question, sending out a new price request to the OO. 238 | /// Failsafe to be used if the priceDisputed callback reverts during execution. 239 | /// @param questionID - The unique questionID 240 | function reset(bytes32 questionID) external onlyAdmin { 241 | QuestionData storage questionData = questions[questionID]; 242 | if (!_isInitialized(questionData)) revert NotInitialized(); 243 | if (questionData.resolved) revert Resolved(); 244 | 245 | // Refund the reward to the question creator if necessary 246 | if (questionData.refund) _refund(questionData); 247 | 248 | // Reset the question, paying for the price request from the caller 249 | _reset(msg.sender, questionID, true, questionData); 250 | } 251 | 252 | /// @notice Allows an admin to resolve a CTF market in an emergency 253 | /// @param questionID - The unique questionID of the question 254 | /// @param payouts - Array of position payouts for the referenced question 255 | function emergencyResolve(bytes32 questionID, uint256[] calldata payouts) external onlyAdmin { 256 | QuestionData storage questionData = questions[questionID]; 257 | 258 | if (!_isValidPayoutArray(payouts)) revert InvalidPayouts(); 259 | if (!_isInitialized(questionData)) revert NotInitialized(); 260 | if (!_isFlagged(questionData)) revert NotFlagged(); 261 | if (block.timestamp < questionData.emergencyResolutionTimestamp) revert SafetyPeriodNotPassed(); 262 | 263 | questionData.resolved = true; 264 | 265 | // Refund the reward to the question creator if necessary 266 | if (questionData.refund) _refund(questionData); 267 | 268 | ctf.reportPayouts(questionID, payouts); 269 | emit QuestionEmergencyResolved(questionID, payouts); 270 | } 271 | 272 | /// @notice Allows an admin to pause market resolution in an emergency 273 | /// @param questionID - The unique questionID of the question 274 | function pause(bytes32 questionID) external onlyAdmin { 275 | QuestionData storage questionData = questions[questionID]; 276 | 277 | if (!_isInitialized(questionData)) revert NotInitialized(); 278 | if (questionData.resolved) revert Resolved(); 279 | 280 | questionData.paused = true; 281 | emit QuestionPaused(questionID); 282 | } 283 | 284 | /// @notice Allows an admin to unpause market resolution in an emergency 285 | /// @param questionID - The unique questionID of the question 286 | function unpause(bytes32 questionID) external onlyAdmin { 287 | QuestionData storage questionData = questions[questionID]; 288 | if (!_isInitialized(questionData)) revert NotInitialized(); 289 | 290 | questionData.paused = false; 291 | emit QuestionUnpaused(questionID); 292 | } 293 | 294 | /*/////////////////////////////////////////////////////////////////// 295 | INTERNAL FUNCTIONS 296 | //////////////////////////////////////////////////////////////////*/ 297 | 298 | function _ready(QuestionData storage questionData) internal view returns (bool) { 299 | if (!_isInitialized(questionData)) return false; 300 | if (questionData.paused) return false; 301 | if (questionData.resolved) return false; 302 | return _hasPrice(questionData); 303 | } 304 | 305 | function _saveQuestion( 306 | address creator, 307 | bytes32 questionID, 308 | bytes memory ancillaryData, 309 | uint256 requestTimestamp, 310 | address rewardToken, 311 | uint256 reward, 312 | uint256 proposalBond, 313 | uint256 liveness 314 | ) internal { 315 | questions[questionID] = QuestionData({ 316 | requestTimestamp: requestTimestamp, 317 | reward: reward, 318 | proposalBond: proposalBond, 319 | liveness: liveness, 320 | emergencyResolutionTimestamp: 0, 321 | resolved: false, 322 | paused: false, 323 | reset: false, 324 | refund: false, 325 | rewardToken: rewardToken, 326 | creator: creator, 327 | ancillaryData: ancillaryData 328 | }); 329 | } 330 | 331 | /// @notice Request a price from the Optimistic Oracle 332 | /// Transfers reward token from the requestor if non-zero reward is specified 333 | /// @param requestor - Address of the requestor 334 | /// @param requestTimestamp - Timestamp used in the OO request 335 | /// @param ancillaryData - Data used to resolve a question 336 | /// @param rewardToken - Address of the reward token 337 | /// @param reward - Reward amount, denominated in rewardToken 338 | /// @param bond - Bond amount used, denominated in rewardToken 339 | /// @param liveness - UMA liveness period, will be the default liveness period if 0. 340 | function _requestPrice( 341 | address requestor, 342 | uint256 requestTimestamp, 343 | bytes memory ancillaryData, 344 | address rewardToken, 345 | uint256 reward, 346 | uint256 bond, 347 | uint256 liveness 348 | ) internal { 349 | if (reward > 0) { 350 | // If the requestor is not the Adapter, the requestor pays for the price request 351 | // If not, the Adapter pays for the price request 352 | if (requestor != address(this)) { 353 | TransferHelper._transferFromERC20(rewardToken, requestor, address(this), reward); 354 | } 355 | 356 | // Approve the OO as spender on the reward token from the Adapter 357 | if (IERC20(rewardToken).allowance(address(this), address(optimisticOracle)) < reward) { 358 | IERC20(rewardToken).approve(address(optimisticOracle), type(uint256).max); 359 | } 360 | } 361 | 362 | // Send a price request to the Optimistic oracle 363 | optimisticOracle.requestPrice( 364 | YES_OR_NO_IDENTIFIER, requestTimestamp, ancillaryData, IERC20(rewardToken), reward 365 | ); 366 | 367 | // Ensure the price request is event based 368 | optimisticOracle.setEventBased(YES_OR_NO_IDENTIFIER, requestTimestamp, ancillaryData); 369 | 370 | // Ensure that the dispute callback flag is set 371 | optimisticOracle.setCallbacks( 372 | YES_OR_NO_IDENTIFIER, 373 | requestTimestamp, 374 | ancillaryData, 375 | false, // DO NOT set callback on priceProposed 376 | true, // DO set callback on priceDisputed 377 | false // DO NOT set callback on priceSettled 378 | ); 379 | 380 | // Update the proposal bond on the Optimistic oracle if necessary 381 | if (bond > 0) optimisticOracle.setBond(YES_OR_NO_IDENTIFIER, requestTimestamp, ancillaryData, bond); 382 | if (liveness > 0) { 383 | optimisticOracle.setCustomLiveness(YES_OR_NO_IDENTIFIER, requestTimestamp, ancillaryData, liveness); 384 | } 385 | } 386 | 387 | /// @notice Reset the question by updating the requestTimestamp field and sending a new price request to the OO 388 | /// @param questionID - The unique questionID 389 | function _reset(address requestor, bytes32 questionID, bool resetRefund, QuestionData storage questionData) 390 | internal 391 | { 392 | uint256 requestTimestamp = block.timestamp; 393 | // Update the question parameters in storage 394 | questionData.requestTimestamp = requestTimestamp; 395 | questionData.reset = true; 396 | if (resetRefund) questionData.refund = false; 397 | 398 | // Send out a new price request with the new timestamp 399 | _requestPrice( 400 | requestor, 401 | requestTimestamp, 402 | questionData.ancillaryData, 403 | questionData.rewardToken, 404 | questionData.reward, 405 | questionData.proposalBond, 406 | questionData.liveness 407 | ); 408 | 409 | emit QuestionReset(questionID); 410 | } 411 | 412 | /// @notice Resolves the underlying CTF market 413 | /// @param questionID - The unique questionID of the question 414 | /// @param questionData - The question data parameters 415 | function _resolve(bytes32 questionID, QuestionData storage questionData) internal { 416 | // Get the price from the OO 417 | int256 price = optimisticOracle.settleAndGetPrice( 418 | YES_OR_NO_IDENTIFIER, questionData.requestTimestamp, questionData.ancillaryData 419 | ); 420 | 421 | // If the OO returns the ignore price, reset the question 422 | if (price == _ignorePrice()) return _reset(address(this), questionID, true, questionData); 423 | 424 | // Set resolved flag 425 | questionData.resolved = true; 426 | 427 | // If refund flag is set, this indicates that the question's reward now sits on the Adapter. 428 | // Refund the reward to the question creator on resolution 429 | if (questionData.refund) _refund(questionData); 430 | 431 | // Construct the payout array for the question 432 | uint256[] memory payouts = _constructPayouts(price); 433 | 434 | // Resolve the underlying CTF market 435 | ctf.reportPayouts(questionID, payouts); 436 | 437 | emit QuestionResolved(questionID, price, payouts); 438 | } 439 | 440 | function _hasPrice(QuestionData storage questionData) internal view returns (bool) { 441 | return optimisticOracle.hasPrice( 442 | address(this), YES_OR_NO_IDENTIFIER, questionData.requestTimestamp, questionData.ancillaryData 443 | ); 444 | } 445 | 446 | function _refund(QuestionData storage questionData) internal { 447 | return TransferHelper._transfer(questionData.rewardToken, questionData.creator, questionData.reward); 448 | } 449 | 450 | function _isFlagged(QuestionData storage questionData) internal view returns (bool) { 451 | return questionData.emergencyResolutionTimestamp > 0; 452 | } 453 | 454 | function _isInitialized(QuestionData storage questionData) internal view returns (bool) { 455 | return questionData.ancillaryData.length > 0; 456 | } 457 | 458 | /// @notice Construct the payout array given the price 459 | /// @param price - The price retrieved from the OO 460 | function _constructPayouts(int256 price) internal pure returns (uint256[] memory) { 461 | // Payouts: [YES, NO] 462 | uint256[] memory payouts = new uint256[](2); 463 | // Valid prices are 0, 0.5 and 1 464 | if (price != 0 && price != 0.5 ether && price != 1 ether) revert InvalidOOPrice(); 465 | 466 | if (price == 0) { 467 | // NO: Report [Yes, No] as [0, 1] 468 | payouts[0] = 0; 469 | payouts[1] = 1; 470 | } else if (price == 0.5 ether) { 471 | // UNKNOWN: Report [Yes, No] as [1, 1], 50/50 472 | // Note that a tie is not a valid outcome when used with the `NegRiskOperator` 473 | payouts[0] = 1; 474 | payouts[1] = 1; 475 | } else { 476 | // YES: Report [Yes, No] as [1, 0] 477 | payouts[0] = 1; 478 | payouts[1] = 0; 479 | } 480 | return payouts; 481 | } 482 | 483 | /// @notice Validates a payout array from the admin 484 | /// @param payouts - The payout array 485 | function _isValidPayoutArray(uint256[] calldata payouts) internal pure returns (bool) { 486 | return PayoutHelperLib.isValidPayoutArray(payouts); 487 | } 488 | 489 | function _ignorePrice() internal pure returns (int256) { 490 | return type(int256).min; 491 | } 492 | } 493 | -------------------------------------------------------------------------------- /src/deploy/Deploy.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { Script } from "forge-std/Script.sol"; 5 | import { UmaCtfAdapter } from "src/UmaCtfAdapter.sol"; 6 | 7 | /// @title Deploy 8 | /// @notice Script to deploy the UmaCtfAdapter 9 | /// @author Polymarket 10 | contract Deploy is Script { 11 | /// @notice Deploys the Adapter 12 | /// @param ctf - The ConditionalTokens Framework address 13 | /// @param finder - The UMA Finder address 14 | function deploy(address ctf, address finder) public returns (address adapter) { 15 | vm.startBroadcast(); 16 | adapter = address(new UmaCtfAdapter(ctf, finder)); 17 | vm.stopBroadcast(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/interfaces/IAddressWhitelist.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | interface IAddressWhitelist { 5 | function addToWhitelist(address) external; 6 | 7 | function removeFromWhitelist(address) external; 8 | 9 | function isOnWhitelist(address) external view returns (bool); 10 | 11 | function getWhitelist() external view returns (address[] memory); 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/IAuth.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.15; 3 | 4 | interface IAuthEE { 5 | error NotAdmin(); 6 | 7 | /// @notice Emitted when a new admin is added 8 | event NewAdmin(address indexed admin, address indexed newAdminAddress); 9 | 10 | /// @notice Emitted when an admin is removed 11 | event RemovedAdmin(address indexed admin, address indexed removedAdmin); 12 | } 13 | 14 | interface IAuth is IAuthEE { 15 | function isAdmin(address) external view returns (bool); 16 | 17 | function addAdmin(address) external; 18 | 19 | function removeAdmin(address) external; 20 | 21 | function renounceAdmin() external; 22 | } 23 | -------------------------------------------------------------------------------- /src/interfaces/IBulletinBoard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | struct AncillaryDataUpdate { 5 | uint256 timestamp; 6 | bytes update; 7 | } 8 | 9 | interface IBulletinBoardEE { 10 | /// @notice Emitted when an ancillary data update is posted 11 | event AncillaryDataUpdated(bytes32 indexed questionID, address indexed owner, bytes update); 12 | } 13 | 14 | interface IBulletinBoard is IBulletinBoardEE { 15 | function postUpdate(bytes32 questionID, bytes memory update) external; 16 | 17 | function getUpdates(bytes32 questionID, address owner) external view returns (AncillaryDataUpdate[] memory); 18 | 19 | function getLatestUpdate(bytes32 questionID, address owner) external view returns (AncillaryDataUpdate memory); 20 | } 21 | -------------------------------------------------------------------------------- /src/interfaces/IConditionalTokens.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { IERC20 } from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | 6 | interface IConditionalTokens { 7 | /// Mapping key is an condition ID. Value represents numerators of the payout vector associated with the condition. This array is initialized with a length equal to the outcome slot count. E.g. Condition with 3 outcomes [A, B, C] and two of those correct [0.5, 0.5, 0]. In Ethereum there are no decimal values, so here, 0.5 is represented by fractions like 1/2 == 0.5. That's why we need numerator and denominator values. Payout numerators are also used as a check of initialization. If the numerators array is empty (has length zero), the condition was not created/prepared. See getOutcomeSlotCount. 8 | function payoutNumerators(bytes32) external returns (uint256[] memory); 9 | 10 | /// Denominator is also used for checking if the condition has been resolved. If the denominator is non-zero, then the condition has been resolved. 11 | function payoutDenominator(bytes32) external returns (uint256); 12 | 13 | /// @dev This function prepares a condition by initializing a payout vector associated with the condition. 14 | /// @param oracle The account assigned to report the result for the prepared condition. 15 | /// @param questionId An identifier for the question to be answered by the oracle. 16 | /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256. 17 | function prepareCondition(address oracle, bytes32 questionId, uint256 outcomeSlotCount) external; 18 | 19 | /// @dev Called by the oracle for reporting results of conditions. Will set the payout vector for the condition with the ID ``keccak256(abi.encodePacked(oracle, questionId, outcomeSlotCount))``, where oracle is the message sender, questionId is one of the parameters of this function, and outcomeSlotCount is the length of the payouts parameter, which contains the payoutNumerators for each outcome slot of the condition. 20 | /// @param questionId The question ID the oracle is answering for 21 | /// @param payouts The oracle's answer 22 | function reportPayouts(bytes32 questionId, uint256[] calldata payouts) external; 23 | 24 | /// @dev This function splits a position. If splitting from the collateral, this contract will attempt to transfer `amount` collateral from the message sender to itself. Otherwise, this contract will burn `amount` stake held by the message sender in the position being split worth of EIP 1155 tokens. Regardless, if successful, `amount` stake will be minted in the split target positions. If any of the transfers, mints, or burns fail, the transaction will revert. The transaction will also revert if the given partition is trivial, invalid, or refers to more slots than the condition is prepared with. 25 | /// @param collateralToken The address of the positions' backing collateral token. 26 | /// @param parentCollectionId The ID of the outcome collections common to the position being split and the split target positions. May be null, in which only the collateral is shared. 27 | /// @param conditionId The ID of the condition to split on. 28 | /// @param partition An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.g. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.g. 0b110 is A|B, 0b010 is B, etc. 29 | /// @param amount The amount of collateral or stake to split. 30 | function splitPosition( 31 | IERC20 collateralToken, 32 | bytes32 parentCollectionId, 33 | bytes32 conditionId, 34 | uint256[] calldata partition, 35 | uint256 amount 36 | ) external; 37 | 38 | function mergePositions( 39 | IERC20 collateralToken, 40 | bytes32 parentCollectionId, 41 | bytes32 conditionId, 42 | uint256[] calldata partition, 43 | uint256 amount 44 | ) external; 45 | 46 | function redeemPositions( 47 | IERC20 collateralToken, 48 | bytes32 parentCollectionId, 49 | bytes32 conditionId, 50 | uint256[] calldata indexSets 51 | ) external; 52 | 53 | /// @dev Gets the outcome slot count of a condition. 54 | /// @param conditionId ID of the condition. 55 | /// @return Number of outcome slots associated with a condition, or zero if condition has not been prepared yet. 56 | function getOutcomeSlotCount(bytes32 conditionId) external view returns (uint256); 57 | 58 | /// @dev Constructs a condition ID from an oracle, a question ID, and the outcome slot count for the question. 59 | /// @param oracle The account assigned to report the result for the prepared condition. 60 | /// @param questionId An identifier for the question to be answered by the oracle. 61 | /// @param outcomeSlotCount The number of outcome slots which should be used for this condition. Must not exceed 256. 62 | function getConditionId(address oracle, bytes32 questionId, uint256 outcomeSlotCount) 63 | external 64 | pure 65 | returns (bytes32); 66 | 67 | /// @dev Constructs an outcome collection ID from a parent collection and an outcome collection. 68 | /// @param parentCollectionId Collection ID of the parent outcome collection, or bytes32(0) if there's no parent. 69 | /// @param conditionId Condition ID of the outcome collection to combine with the parent outcome collection. 70 | /// @param indexSet Index set of the outcome collection to combine with the parent outcome collection. 71 | function getCollectionId(bytes32 parentCollectionId, bytes32 conditionId, uint256 indexSet) 72 | external 73 | view 74 | returns (bytes32); 75 | 76 | /// @dev Constructs a position ID from a collateral token and an outcome collection. These IDs are used as the ERC-1155 ID for this contract. 77 | /// @param collateralToken Collateral token which backs the position. 78 | /// @param collectionId ID of the outcome collection associated with this position. 79 | function getPositionId(IERC20 collateralToken, bytes32 collectionId) external pure returns (uint256); 80 | } 81 | -------------------------------------------------------------------------------- /src/interfaces/IFinder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | /** 5 | * @title Provides addresses of the live contracts implementing certain interfaces. 6 | * @dev Examples are the Oracle or Store interfaces. 7 | */ 8 | interface IFinder { 9 | /** 10 | * @notice Updates the address of the contract that implements `interfaceName`. 11 | * @param interfaceName bytes32 encoding of the interface name that is either changed or registered. 12 | * @param implementationAddress address of the deployed contract that implements the interface. 13 | */ 14 | function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external; 15 | 16 | /** 17 | * @notice Gets the address of the contract that implements the given `interfaceName`. 18 | * @param interfaceName queried interface. 19 | * @return implementationAddress address of the deployed contract that implements the interface. 20 | */ 21 | function getImplementationAddress(bytes32 interfaceName) external view returns (address); 22 | } 23 | -------------------------------------------------------------------------------- /src/interfaces/IOptimisticOracleV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; 5 | 6 | struct RequestSettings { 7 | bool eventBased; // True if the request is set to be event-based. 8 | bool refundOnDispute; // True if the requester should be refunded their reward on dispute. 9 | bool callbackOnPriceProposed; // True if callbackOnPriceProposed callback is required. 10 | bool callbackOnPriceDisputed; // True if callbackOnPriceDisputed callback is required. 11 | bool callbackOnPriceSettled; // True if callbackOnPriceSettled callback is required. 12 | uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee. 13 | uint256 customLiveness; // Custom liveness value set by the requester. 14 | } 15 | 16 | // Struct representing a price request. 17 | struct Request { 18 | address proposer; // Address of the proposer. 19 | address disputer; // Address of the disputer. 20 | IERC20 currency; // ERC20 token used to pay rewards and fees. 21 | bool settled; // True if the request is settled. 22 | RequestSettings requestSettings; // Custom settings associated with a request. 23 | int256 proposedPrice; // Price that the proposer submitted. 24 | int256 resolvedPrice; // Price resolved once the request is settled. 25 | uint256 expirationTime; // Time at which the request auto-settles without a dispute. 26 | uint256 reward; // Amount of the currency to pay to the proposer on settlement. 27 | uint256 finalFee; // Final fee to pay to the Store upon request to the DVM. 28 | } 29 | 30 | /// @title Optimistic Oracle V2 Interface 31 | interface IOptimisticOracleV2 { 32 | /// @notice Requests a new price. 33 | /// @param identifier price identifier being requested. 34 | /// @param timestamp timestamp of the price being requested. 35 | /// @param ancillaryData ancillary data representing additional args being passed with the price request. 36 | /// @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM. 37 | /// @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0, 38 | /// which could make sense if the contract requests and proposes the value in the same call or 39 | /// provides its own reward system. 40 | /// @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay. 41 | /// This can be changed with a subsequent call to setBond(). 42 | function requestPrice( 43 | bytes32 identifier, 44 | uint256 timestamp, 45 | bytes memory ancillaryData, 46 | IERC20 currency, 47 | uint256 reward 48 | ) external returns (uint256 totalBond); 49 | 50 | /// @notice Proposes a price value for an existing price request. 51 | /// @param requester sender of the initial price request. 52 | /// @param identifier price identifier to identify the existing request. 53 | /// @param timestamp timestamp to identify the existing request. 54 | /// @param ancillaryData ancillary data of the price being requested. 55 | /// @param proposedPrice price being proposed. 56 | /// @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to 57 | /// the proposer once settled if the proposal is correct. 58 | function proposePrice( 59 | address requester, 60 | bytes32 identifier, 61 | uint256 timestamp, 62 | bytes memory ancillaryData, 63 | int256 proposedPrice 64 | ) external returns (uint256 totalBond); 65 | 66 | /// @notice Disputes a price value for an existing price request with an active proposal. 67 | /// @param requester sender of the initial price request. 68 | /// @param identifier price identifier to identify the existing request. 69 | /// @param timestamp timestamp to identify the existing request. 70 | /// @param ancillaryData ancillary data of the price being requested. 71 | /// @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to 72 | /// the disputer once settled if the dispute was valid (the proposal was incorrect). 73 | function disputePrice(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) 74 | external 75 | returns (uint256 totalBond); 76 | 77 | /// @notice Set the proposal bond associated with a price request. 78 | /// @param identifier price identifier to identify the existing request. 79 | /// @param timestamp timestamp to identify the existing request. 80 | /// @param ancillaryData ancillary data of the price being requested. 81 | /// @param bond custom bond amount to set. 82 | /// @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be 83 | /// changed again with a subsequent call to setBond(). 84 | function setBond(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 bond) 85 | external 86 | returns (uint256 totalBond); 87 | 88 | /// @notice Sets the request to be an "event-based" request. 89 | /// @dev Calling this method has a few impacts on the request: 90 | /// 91 | /// 1. The timestamp at which the request is evaluated is the time of the proposal, not the timestamp associated 92 | /// with the request. 93 | /// 94 | /// 2. The proposer cannot propose the "too early" value (TOO_EARLY_RESPONSE). This is to ensure that a proposer who 95 | /// prematurely proposes a response loses their bond. 96 | /// 97 | /// 3. RefundoOnDispute is automatically set, meaning disputes trigger the reward to be automatically refunded to 98 | /// the requesting contract. 99 | /// 100 | /// @param identifier price identifier to identify the existing request. 101 | /// @param timestamp timestamp to identify the existing request. 102 | /// @param ancillaryData ancillary data of the price being requested. 103 | function setEventBased(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) external; 104 | 105 | /// @notice Sets which callbacks should be enabled for the request. 106 | /// @param identifier price identifier to identify the existing request. 107 | /// @param timestamp timestamp to identify the existing request. 108 | /// @param ancillaryData ancillary data of the price being requested. 109 | /// @param callbackOnPriceProposed whether to enable the callback onPriceProposed. 110 | /// @param callbackOnPriceDisputed whether to enable the callback onPriceDisputed. 111 | /// @param callbackOnPriceSettled whether to enable the callback onPriceSettled. 112 | function setCallbacks( 113 | bytes32 identifier, 114 | uint256 timestamp, 115 | bytes memory ancillaryData, 116 | bool callbackOnPriceProposed, 117 | bool callbackOnPriceDisputed, 118 | bool callbackOnPriceSettled 119 | ) external; 120 | 121 | /// @notice Sets a custom liveness value for the request. Liveness is the amount of time a proposal must wait before 122 | /// being auto-resolved. 123 | /// @param identifier price identifier to identify the existing request. 124 | /// @param timestamp timestamp to identify the existing request. 125 | /// @param ancillaryData ancillary data of the price being requested. 126 | /// @param customLiveness new custom liveness. 127 | function setCustomLiveness( 128 | bytes32 identifier, 129 | uint256 timestamp, 130 | bytes memory ancillaryData, 131 | uint256 customLiveness 132 | ) external; 133 | 134 | /// @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable. 135 | /// @param requester sender of the initial price request. 136 | /// @param identifier price identifier to identify the existing request. 137 | /// @param timestamp timestamp to identify the existing request. 138 | /// @param ancillaryData ancillary data of the price being requested. 139 | /// @return payout the amount that the "winner" (proposer or disputer) receives on settlement. This amount includes 140 | /// the returned bonds as well as additional rewards. 141 | function settle(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) 142 | external 143 | returns (uint256 payout); 144 | 145 | /// @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled 146 | /// or settleable. Note: this method is not view so that this call may actually settle the price request if it 147 | /// hasn't been settled. 148 | /// @param identifier price identifier to identify the existing request. 149 | /// @param timestamp timestamp to identify the existing request. 150 | /// @param ancillaryData ancillary data of the price being requested. 151 | /// @return resolved price. 152 | //// 153 | function settleAndGetPrice(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) 154 | external 155 | returns (int256); 156 | 157 | /// @notice Gets the current data structure containing all information about a price request. 158 | /// @param requester sender of the initial price request. 159 | /// @param identifier price identifier to identify the existing request. 160 | /// @param timestamp timestamp to identify the existing request. 161 | /// @param ancillaryData ancillary data of the price being requested. 162 | /// @return the Request data structure. 163 | //// 164 | function getRequest(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) 165 | external 166 | view 167 | returns (Request memory); 168 | 169 | /// @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price). 170 | /// @param requester sender of the initial price request. 171 | /// @param identifier price identifier to identify the existing request. 172 | /// @param timestamp timestamp to identify the existing request. 173 | /// @param ancillaryData ancillary data of the price being requested. 174 | /// @return true if price has resolved or settled, false otherwise. 175 | function hasPrice(address requester, bytes32 identifier, uint256 timestamp, bytes memory ancillaryData) 176 | external 177 | view 178 | returns (bool); 179 | 180 | function defaultLiveness() external view returns (uint256); 181 | } 182 | -------------------------------------------------------------------------------- /src/interfaces/IOptimisticRequester.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | /// @title Optimistic Requester 5 | interface IOptimisticRequester { 6 | /// @notice Callback for disputes. 7 | /// @param identifier price identifier being requested. 8 | /// @param timestamp timestamp of the price being requested. 9 | /// @param ancillaryData ancillary data of the price being requested. 10 | /// @param refund refund received in the case that refundOnDispute was enabled. 11 | function priceDisputed(bytes32 identifier, uint256 timestamp, bytes memory ancillaryData, uint256 refund) 12 | external; 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/IUmaCtfAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.15; 3 | 4 | struct QuestionData { 5 | /// @notice Request timestamp, set when a request is made to the Optimistic Oracle 6 | /// @dev Used to identify the request and NOT used by the DVM to determine validity 7 | uint256 requestTimestamp; 8 | /// @notice Reward offered to a successful proposer 9 | uint256 reward; 10 | /// @notice Additional bond required by Optimistic oracle proposers/disputers 11 | uint256 proposalBond; 12 | /// @notice Custom liveness period 13 | uint256 liveness; 14 | /// @notice Emergency resolution timestamp, set when a market is flagged for emergency resolution 15 | uint256 emergencyResolutionTimestamp; 16 | /// @notice Flag marking whether a question is resolved 17 | bool resolved; 18 | /// @notice Flag marking whether a question is paused 19 | bool paused; 20 | /// @notice Flag marking whether a question has been reset. A question can only be reset once 21 | bool reset; 22 | /// @notice Flag marking whether a question's reward should be refunded. 23 | bool refund; 24 | /// @notice ERC20 token address used for payment of rewards, proposal bonds and fees 25 | address rewardToken; 26 | /// @notice The address of the question creator 27 | address creator; 28 | /// @notice Data used to resolve a condition 29 | bytes ancillaryData; 30 | } 31 | 32 | interface IUmaCtfAdapterEE { 33 | error NotInitialized(); 34 | error NotFlagged(); 35 | error NotReadyToResolve(); 36 | error Resolved(); 37 | error Initialized(); 38 | error UnsupportedToken(); 39 | error Flagged(); 40 | error Paused(); 41 | error SafetyPeriodPassed(); 42 | error SafetyPeriodNotPassed(); 43 | error PriceNotAvailable(); 44 | error InvalidAncillaryData(); 45 | error NotOptimisticOracle(); 46 | error InvalidOOPrice(); 47 | error InvalidPayouts(); 48 | 49 | /// @notice Emitted when a questionID is initialized 50 | event QuestionInitialized( 51 | bytes32 indexed questionID, 52 | uint256 indexed requestTimestamp, 53 | address indexed creator, 54 | bytes ancillaryData, 55 | address rewardToken, 56 | uint256 reward, 57 | uint256 proposalBond 58 | ); 59 | 60 | /// @notice Emitted when a question is paused by an authorized user 61 | event QuestionPaused(bytes32 indexed questionID); 62 | 63 | /// @notice Emitted when a question is unpaused by an authorized user 64 | event QuestionUnpaused(bytes32 indexed questionID); 65 | 66 | /// @notice Emitted when a question is flagged by an admin for emergency resolution 67 | event QuestionFlagged(bytes32 indexed questionID); 68 | 69 | /// @notice Emitted when a question is unflagged by an admin 70 | event QuestionUnflagged(bytes32 indexed questionID); 71 | 72 | /// @notice Emitted when a question is reset 73 | event QuestionReset(bytes32 indexed questionID); 74 | 75 | /// @notice Emitted when a question is resolved 76 | event QuestionResolved(bytes32 indexed questionID, int256 indexed settledPrice, uint256[] payouts); 77 | 78 | /// @notice Emitted when a question is emergency resolved 79 | event QuestionEmergencyResolved(bytes32 indexed questionID, uint256[] payouts); 80 | } 81 | 82 | interface IUmaCtfAdapter is IUmaCtfAdapterEE { 83 | function initialize( 84 | bytes memory ancillaryData, 85 | address rewardToken, 86 | uint256 reward, 87 | uint256 proposalBond, 88 | uint256 liveness 89 | ) external returns (bytes32); 90 | 91 | function ready(bytes32 questionID) external view returns (bool); 92 | 93 | function resolve(bytes32 questionID) external; 94 | 95 | function flag(bytes32 questionID) external; 96 | 97 | function reset(bytes32 questionID) external; 98 | 99 | function pause(bytes32 questionID) external; 100 | 101 | function unpause(bytes32 questionID) external; 102 | 103 | function getQuestion(bytes32 questionID) external returns (QuestionData memory); 104 | } 105 | -------------------------------------------------------------------------------- /src/libraries/AncillaryDataLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | library AncillaryDataLib { 5 | string private constant INITIALIZER_PREFIX = ",initializer:"; 6 | 7 | /// @notice Appends the initializer address to the ancillaryData 8 | /// @param initializer - The initializer address 9 | /// @param ancillaryData - The ancillary data 10 | function _appendAncillaryData(address initializer, bytes memory ancillaryData) 11 | internal 12 | pure 13 | returns (bytes memory) 14 | { 15 | return abi.encodePacked(ancillaryData, INITIALIZER_PREFIX, _toUtf8BytesAddress(initializer)); 16 | } 17 | 18 | /// @notice Returns a UTF8-encoded address 19 | /// Source: UMA Protocol's AncillaryDataLib 20 | /// https://github.com/UMAprotocol/protocol/blob/9967e70e7db3f262fde0dc9d89ea04d4cd11ed97/packages/core/contracts/common/implementation/AncillaryData.sol 21 | /// Will return address in all lower case characters and without the leading 0x. 22 | /// @param addr - The address to encode. 23 | function _toUtf8BytesAddress(address addr) internal pure returns (bytes memory) { 24 | return abi.encodePacked( 25 | _toUtf8Bytes32Bottom(bytes32(bytes20(addr)) >> 128), bytes8(_toUtf8Bytes32Bottom(bytes20(addr))) 26 | ); 27 | } 28 | 29 | /// @notice Converts the bottom half of a bytes32 input to hex in a highly gas-optimized way. 30 | /// Source: the brilliant implementation at https://gitter.im/ethereum/solidity?at=5840d23416207f7b0ed08c9b. 31 | function _toUtf8Bytes32Bottom(bytes32 bytesIn) private pure returns (bytes32) { 32 | unchecked { 33 | uint256 x = uint256(bytesIn); 34 | 35 | // Nibble interleave 36 | x = x & 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff; 37 | x = (x | (x * 2 ** 64)) & 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff; 38 | x = (x | (x * 2 ** 32)) & 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff; 39 | x = (x | (x * 2 ** 16)) & 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff; 40 | x = (x | (x * 2 ** 8)) & 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff; 41 | x = (x | (x * 2 ** 4)) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f; 42 | 43 | // Hex encode 44 | uint256 h = (x & 0x0808080808080808080808080808080808080808080808080808080808080808) / 8; 45 | uint256 i = (x & 0x0404040404040404040404040404040404040404040404040404040404040404) / 4; 46 | uint256 j = (x & 0x0202020202020202020202020202020202020202020202020202020202020202) / 2; 47 | x = x + (h & (i | j)) * 0x27 + 0x3030303030303030303030303030303030303030303030303030303030303030; 48 | 49 | // Return the result. 50 | return bytes32(x); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/libraries/PayoutHelperLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | library PayoutHelperLib { 5 | 6 | function isValidPayoutArray(uint256[] memory payouts) internal pure returns (bool) { 7 | if (payouts.length != 2) return false; 8 | 9 | // Payout must be [0,1], [1,0] or [1,1] 10 | // if payout[0] is 1, payout[1] must be 0 or 1 11 | if ((payouts[0] == 1) && (payouts[1] == 0 || payouts[1] == 1)) { 12 | return true; 13 | } 14 | 15 | // If payout[0] is 0, payout[1] must be 1 16 | if ((payouts[0] == 0) && (payouts[1] == 1)) { 17 | return true; 18 | } 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/libraries/TransferHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { SafeTransferLib, ERC20 } from "lib/solmate/src/utils/SafeTransferLib.sol"; 5 | 6 | /// @title TransferHelper 7 | /// @notice Helper library to transfer tokens 8 | library TransferHelper { 9 | /// @notice Transfers tokens from the targeted address to the given destination 10 | /// @param token - The contract address of the token to be transferred 11 | /// @param from - The originating address from which the tokens will be transferred 12 | /// @param to - The destination address of the transfer 13 | /// @param amount - The amount to be transferred 14 | function _transferFromERC20(address token, address from, address to, uint256 amount) internal { 15 | SafeTransferLib.safeTransferFrom(ERC20(token), from, to, amount); 16 | } 17 | 18 | /// @notice Transfers tokens from the current address to the given destination 19 | /// @param token - The contract address of the token to be transferred 20 | /// @param to - The destination address of the transfer 21 | /// @param amount - The amount to be transferred 22 | function _transfer(address token, address to, uint256 amount) internal { 23 | SafeTransferLib.safeTransfer(ERC20(token), to, amount); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/mixins/Auth.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { IAuth } from "../interfaces/IAuth.sol"; 5 | 6 | /// @title Auth 7 | /// @notice Provides access control modifiers 8 | abstract contract Auth is IAuth { 9 | /// @notice Auth 10 | mapping(address => uint256) public admins; 11 | 12 | modifier onlyAdmin() { 13 | if (admins[msg.sender] != 1) revert NotAdmin(); 14 | _; 15 | } 16 | 17 | constructor() { 18 | admins[msg.sender] = 1; 19 | } 20 | 21 | /// @notice Adds an Admin 22 | /// @param admin - The address of the admin 23 | function addAdmin(address admin) external onlyAdmin { 24 | admins[admin] = 1; 25 | emit NewAdmin(msg.sender, admin); 26 | } 27 | 28 | /// @notice Removes an admin 29 | /// @param admin - The address of the admin to be removed 30 | function removeAdmin(address admin) external onlyAdmin { 31 | admins[admin] = 0; 32 | emit RemovedAdmin(msg.sender, admin); 33 | } 34 | 35 | /// @notice Renounces Admin privileges from the caller 36 | function renounceAdmin() external onlyAdmin { 37 | admins[msg.sender] = 0; 38 | emit RemovedAdmin(msg.sender, msg.sender); 39 | } 40 | 41 | /// @notice Checks if an address is an admin 42 | /// @param addr - The address to be checked 43 | function isAdmin(address addr) external view returns (bool) { 44 | return admins[addr] == 1; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/mixins/BulletinBoard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { IBulletinBoard, AncillaryDataUpdate } from "src/interfaces/IBulletinBoard.sol"; 5 | 6 | /// @title Bulletin Board 7 | /// @notice A registry containing ancillary data updates 8 | abstract contract BulletinBoard is IBulletinBoard { 9 | /// @notice Mapping to an array of Ancillary data updates for questions 10 | mapping(bytes32 => AncillaryDataUpdate[]) public updates; 11 | 12 | /// @notice Post an update for the question 13 | /// Anyone can post an update for any questionID, but users should only consider updates posted by the question creator 14 | /// @param questionID - The unique questionID 15 | /// @param update - The update for the question 16 | function postUpdate(bytes32 questionID, bytes memory update) external { 17 | bytes32 id = keccak256(abi.encode(questionID, msg.sender)); 18 | updates[id].push(AncillaryDataUpdate({ timestamp: block.timestamp, update: update })); 19 | emit AncillaryDataUpdated(questionID, msg.sender, update); 20 | } 21 | 22 | /// @notice Gets all updates for a questionID and owner 23 | /// @param questionID - The unique questionID 24 | /// @param owner - The address of the question initializer 25 | function getUpdates(bytes32 questionID, address owner) public view returns (AncillaryDataUpdate[] memory) { 26 | return updates[keccak256(abi.encode(questionID, owner))]; 27 | } 28 | 29 | /// @notice Gets the latest update for a questionID and owner 30 | /// @param questionID - The unique questionID 31 | /// @param owner - The address of the question initializer 32 | function getLatestUpdate(bytes32 questionID, address owner) external view returns (AncillaryDataUpdate memory) { 33 | AncillaryDataUpdate[] memory currentUpdates = getUpdates(questionID, owner); 34 | if (currentUpdates.length == 0) return AncillaryDataUpdate({ timestamp: 0, update: "" }); 35 | return currentUpdates[currentUpdates.length - 1]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/dev/AdapterHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { ERC20 } from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; 5 | 6 | import { Deployer } from "./Deployer.sol"; 7 | import { TestHelper } from "./TestHelper.sol"; 8 | import { MintableERC20 } from "./MintableERC20.sol"; 9 | import { OracleStub } from "./OracleStub.sol"; 10 | 11 | import { UmaCtfAdapter } from "src/UmaCtfAdapter.sol"; 12 | import { IFinder } from "src/interfaces/IFinder.sol"; 13 | import { IAddressWhitelist } from "src/interfaces/IAddressWhitelist.sol"; 14 | 15 | import { IAuthEE } from "src/interfaces/IAuth.sol"; 16 | import { PayoutHelperLib } from "src/libraries/PayoutHelperLib.sol"; 17 | import { AncillaryDataLib } from "src/libraries/AncillaryDataLib.sol"; 18 | import { IConditionalTokens } from "src/interfaces/IConditionalTokens.sol"; 19 | import { QuestionData, IUmaCtfAdapterEE } from "src/interfaces/IUmaCtfAdapter.sol"; 20 | import { IOptimisticOracleV2, Request } from "src/interfaces/IOptimisticOracleV2.sol"; 21 | 22 | struct Unsigned { 23 | uint256 rawValue; 24 | } 25 | 26 | interface IStore { 27 | function setFinalFee(address currency, Unsigned memory newFinalFee) external; 28 | } 29 | 30 | interface IIdentifierWhitelist { 31 | function addSupportedIdentifier(bytes32) external; 32 | } 33 | 34 | abstract contract AdapterHelper is TestHelper, IAuthEE, IUmaCtfAdapterEE { 35 | address public admin = alice; 36 | address public proposer = brian; 37 | address public disputer = henry; 38 | UmaCtfAdapter public adapter; 39 | address public usdc; 40 | address public ctf; 41 | address public optimisticOracle; 42 | address public finder; 43 | address public whitelist; 44 | OracleStub public oracle; 45 | 46 | bytes32 public conditionId; 47 | 48 | // Bytes of 'q: title: Will it rain in NYC on Wednesday, description: Will it rain in NYC on Wednesday' 49 | bytes public constant ancillaryData = 50 | hex"713a207469746c653a2057696c6c206974207261696e20696e204e5943206f6e205765646e65736461792c206465736372697074696f6e3a2057696c6c206974207261696e20696e204e5943206f6e205765646e6573646179"; 51 | bytes public appendedAncillaryData = AncillaryDataLib._appendAncillaryData(admin, ancillaryData); 52 | bytes32 public questionID = keccak256(appendedAncillaryData); 53 | bytes32 public constant identifier = "YES_OR_NO_QUERY"; 54 | 55 | event Transfer(address indexed from, address indexed to, uint256 value); 56 | 57 | event ConditionResolution( 58 | bytes32 indexed conditionId, 59 | address indexed oracle, 60 | bytes32 indexed questionId, 61 | uint256 outcomeSlotCount, 62 | uint256[] payoutNumerators 63 | ); 64 | 65 | function setUp() public virtual { 66 | vm.label(admin, "Admin"); 67 | vm.label(proposer, "Proposer"); 68 | vm.label(disputer, "Disputer"); 69 | 70 | // Deploy Collateral and ConditionalTokens Framework 71 | usdc = deployToken("USD Coin", "USD"); 72 | vm.label(usdc, "USDC"); 73 | ctf = Deployer.ConditionalTokens(); 74 | 75 | // Setup UMA Contracts 76 | setupUmaContracts(); 77 | 78 | // Deploy adapter 79 | vm.startPrank(admin); 80 | adapter = new UmaCtfAdapter(ctf, finder); 81 | 82 | conditionId = IConditionalTokens(ctf).getConditionId(address(adapter), questionID, 2); 83 | 84 | // Mint USDC to Admin and approve on Adapter 85 | dealAndApprove(usdc, admin, address(adapter), 1_000_000_000_000); 86 | vm.stopPrank(); 87 | 88 | // Mint USDC to Proposer and Disputer and approve the OptimisticOracle as spender 89 | vm.startPrank(proposer); 90 | dealAndApprove(usdc, proposer, optimisticOracle, 1_000_000_000_000); 91 | vm.stopPrank(); 92 | 93 | vm.startPrank(disputer); 94 | dealAndApprove(usdc, disputer, optimisticOracle, 1_000_000_000_000); 95 | vm.stopPrank(); 96 | } 97 | 98 | function setupUmaContracts() internal { 99 | // Deploy Store 100 | address store = Deployer.Store(); 101 | // Set final fee for USDC 102 | IStore(store).setFinalFee(usdc, Unsigned({ rawValue: 1500000000 })); 103 | 104 | address identifierWhitelist = Deployer.IdentifierWhitelist(); 105 | // Add YES_OR_NO_QUERY to Identifier Whitelist 106 | IIdentifierWhitelist(identifierWhitelist).addSupportedIdentifier("YES_OR_NO_QUERY"); 107 | 108 | // Deploy Collateral whitelist 109 | whitelist = Deployer.AddressWhitelist(); 110 | // Add USDC to whitelist 111 | IAddressWhitelist(whitelist).addToWhitelist(usdc); 112 | 113 | // Deploy Oracle(Voting) 114 | oracle = new OracleStub(); 115 | 116 | // Deploy Finder 117 | finder = Deployer.Finder(); 118 | // Deploy Optimistic Oracle 119 | optimisticOracle = Deployer.OptimisticOracleV2(7200, finder); 120 | 121 | // Add contracts to Finder 122 | IFinder(finder).changeImplementationAddress("IdentifierWhitelist", identifierWhitelist); 123 | IFinder(finder).changeImplementationAddress("Store", store); 124 | IFinder(finder).changeImplementationAddress("OptimisticOracleV2", optimisticOracle); 125 | IFinder(finder).changeImplementationAddress("CollateralWhitelist", whitelist); 126 | IFinder(finder).changeImplementationAddress("Oracle", address(oracle)); 127 | } 128 | 129 | function isValidPayoutArray(uint256[] memory payouts) public pure returns (bool) { 130 | return PayoutHelperLib.isValidPayoutArray(payouts); 131 | } 132 | 133 | function settle(uint256 timestamp, bytes memory data) internal { 134 | fastForward(10); 135 | vm.prank(proposer); 136 | IOptimisticOracleV2(optimisticOracle).settle(address(adapter), identifier, timestamp, data); 137 | } 138 | 139 | function getRequest(uint256 timestamp, bytes memory data) internal view returns (Request memory) { 140 | return IOptimisticOracleV2(optimisticOracle).getRequest(address(adapter), identifier, timestamp, data); 141 | } 142 | 143 | function propose(int256 price, uint256 timestamp, bytes memory data) internal { 144 | fastForward(10); 145 | vm.prank(proposer); 146 | IOptimisticOracleV2(optimisticOracle).proposePrice(address(adapter), identifier, timestamp, data, price); 147 | } 148 | 149 | function dispute(uint256 timestamp, bytes memory data) internal { 150 | fastForward(10); 151 | vm.prank(disputer); 152 | IOptimisticOracleV2(optimisticOracle).disputePrice(address(adapter), identifier, timestamp, data); 153 | } 154 | 155 | function proposeAndSettle(int256 price, uint256 timestamp, bytes memory data) internal { 156 | // Propose a price for the request 157 | propose(price, timestamp, data); 158 | 159 | // Advance time past the request expiration time 160 | fastForward(1000); 161 | 162 | // Settle the request 163 | settle(timestamp, data); 164 | } 165 | 166 | function getDefaultLiveness() internal view returns (uint256) { 167 | return IOptimisticOracleV2(optimisticOracle).defaultLiveness(); 168 | } 169 | 170 | function deployToken(string memory name, string memory symbol) internal returns (address token) { 171 | token = address(new MintableERC20(name, symbol)); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/test/dev/Deployer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.15; 3 | 4 | import { Vm } from "forge-std/Vm.sol"; 5 | 6 | library Deployer { 7 | Vm public constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); 8 | 9 | function _deployCode(string memory _what) internal returns (address addr) { 10 | return _deployCode(_what, ""); 11 | } 12 | 13 | function _deployCode(string memory _what, bytes memory _args) internal returns (address addr) { 14 | bytes memory bytecode = abi.encodePacked(vm.getCode(_what), _args); 15 | assembly { 16 | addr := create(0, add(bytecode, 0x20), mload(bytecode)) 17 | } 18 | } 19 | 20 | function ConditionalTokens() public returns (address) { 21 | address deployment = _deployCode("artifacts/ConditionalTokens.json"); 22 | vm.label(deployment, "ConditionalTokens"); 23 | return deployment; 24 | } 25 | 26 | function OptimisticOracleV2(uint256 liveness, address finder) public returns (address) { 27 | bytes memory args = abi.encode(liveness, finder, address(0)); 28 | address deployment = _deployCode("artifacts/OptimisticOracleV2.json", args); 29 | vm.label(deployment, "OptimisticOracleV2"); 30 | return deployment; 31 | } 32 | 33 | function Store() public returns (address) { 34 | address deployment = _deployCode("artifacts/Store.json"); 35 | vm.label(deployment, "Store"); 36 | return deployment; 37 | } 38 | 39 | function IdentifierWhitelist() public returns (address) { 40 | address deployment = _deployCode("artifacts/IdentifierWhitelist.json"); 41 | vm.label(deployment, "IdentifierWhitelist"); 42 | return deployment; 43 | } 44 | 45 | function AddressWhitelist() public returns (address) { 46 | address deployment = _deployCode("artifacts/AddressWhitelist.json"); 47 | vm.label(deployment, "AddressWhitelist"); 48 | return deployment; 49 | } 50 | 51 | function Finder() public returns (address) { 52 | address deployment = _deployCode("artifacts/Finder.json"); 53 | vm.label(deployment, "Finder"); 54 | return deployment; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/dev/MintableERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { ERC20 } from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract MintableERC20 is ERC20 { 7 | constructor(string memory name, string memory symbol) ERC20(name, symbol) { } 8 | 9 | function mint(address _to, uint256 _amount) external { 10 | _mint(_to, _amount); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/dev/OracleStub.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | /// @notice Stub contract used to mock UMA's Voting.sol(or OracleChildTunnel on Polygon) 5 | contract OracleStub { 6 | bool public priceExists; 7 | int256 public price; 8 | 9 | function requestPrice(bytes32, uint256, bytes memory) public { 10 | // no-op 11 | } 12 | 13 | function hasPrice(bytes32, uint256, bytes memory) public view returns (bool) { 14 | return priceExists; 15 | } 16 | 17 | function getPrice(bytes32, uint256, bytes memory) public view returns (int256) { 18 | return price; 19 | } 20 | 21 | function setPriceExists(bool _priceExists) public { 22 | priceExists = _priceExists; 23 | } 24 | 25 | function setPrice(int256 _price) public { 26 | price = _price; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/dev/TestHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { Test, console2 as console, stdStorage, StdStorage, stdError } from "forge-std/Test.sol"; 5 | import { ERC20 } from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; 6 | 7 | abstract contract TestHelper is Test { 8 | mapping(address => mapping(address => uint256)) private balanceCheckpoints; 9 | 10 | address public alice = address(1); 11 | address public brian = address(2); 12 | address public carla = address(3); 13 | address public dylan = address(4); 14 | address public erica = address(5); 15 | address public frank = address(6); 16 | address public grace = address(7); 17 | address public henry = address(8); 18 | 19 | constructor() { 20 | vm.label(alice, "Alice"); 21 | vm.label(brian, "Brian"); 22 | vm.label(carla, "Carla"); 23 | vm.label(dylan, "Dylan"); 24 | vm.label(erica, "Erica"); 25 | vm.label(frank, "Frank"); 26 | vm.label(grace, "Grace"); 27 | vm.label(henry, "Henry"); 28 | } 29 | 30 | modifier with(address _account) { 31 | vm.startPrank(_account); 32 | _; 33 | vm.stopPrank(); 34 | } 35 | 36 | function assertBalance(address _token, address _who, uint256 _amount) internal { 37 | assertEq(ERC20(_token).balanceOf(_who), balanceCheckpoints[_token][_who] + _amount); 38 | } 39 | 40 | function checkpointBalance(address _token, address _who) internal { 41 | balanceCheckpoints[_token][_who] = balanceOf(_token, _who); 42 | } 43 | 44 | function balanceOf(address _token, address _who) internal view returns (uint256) { 45 | return ERC20(_token).balanceOf(_who); 46 | } 47 | 48 | function approve(address _token, address _spender, uint256 _amount) internal { 49 | ERC20(_token).approve(_spender, _amount); 50 | } 51 | 52 | ///@dev msg.sender is the owner of the approved tokens 53 | function dealAndApprove(address _token, address _to, address _spender, uint256 _amount) internal { 54 | deal(_token, _to, _amount); 55 | approve(_token, _spender, _amount); 56 | } 57 | 58 | function advance(uint256 _delta) internal { 59 | vm.roll(block.number + _delta); 60 | } 61 | 62 | function fastForward(uint256 blockNumberDelta) internal { 63 | uint256 tsDelta = 12 * blockNumberDelta; 64 | vm.roll(block.number + blockNumberDelta); 65 | vm.warp(block.timestamp + tsDelta); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/mixins/Auth.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | 6 | import { Auth } from "src/mixins/Auth.sol"; 7 | import { IAuthEE } from "src/interfaces/IAuth.sol"; 8 | 9 | contract AuthHarness is Auth { 10 | function useOnlyAdmin() public onlyAdmin { } 11 | } 12 | 13 | contract AuthTest is Test, IAuthEE { 14 | address admin = address(1); 15 | address brian = address(2); 16 | address carla = address(3); 17 | 18 | AuthHarness public harness; 19 | 20 | function setUp() public { 21 | vm.prank(admin); 22 | harness = new AuthHarness(); 23 | } 24 | 25 | function testIsAdmin() public { 26 | assertTrue(harness.isAdmin(admin)); 27 | assertFalse(harness.isAdmin(brian)); 28 | } 29 | 30 | function testAddAdmin() public { 31 | vm.expectEmit(true, true, true, true); 32 | emit NewAdmin(admin, brian); 33 | 34 | vm.prank(admin); 35 | harness.addAdmin(brian); 36 | } 37 | 38 | function testOnlyAdminSuccess() public { 39 | vm.prank(admin); 40 | harness.useOnlyAdmin(); 41 | } 42 | 43 | function testOnlyAdminRevert() public { 44 | vm.expectRevert(NotAdmin.selector); 45 | harness.useOnlyAdmin(); 46 | } 47 | 48 | function testAddAdminRevert() public { 49 | vm.prank(brian); 50 | vm.expectRevert(NotAdmin.selector); 51 | harness.addAdmin(brian); 52 | } 53 | 54 | function testRemoveAdmin() public { 55 | vm.prank(admin); 56 | harness.addAdmin(carla); 57 | 58 | vm.expectEmit(true, true, true, true); 59 | emit RemovedAdmin(admin, carla); 60 | 61 | vm.prank(admin); 62 | harness.removeAdmin(carla); 63 | 64 | assertFalse(harness.isAdmin(carla)); 65 | } 66 | 67 | function testRenounceAdmin() public { 68 | vm.prank(admin); 69 | harness.renounceAdmin(); 70 | emit RemovedAdmin(admin, admin); 71 | 72 | assertFalse(harness.isAdmin(admin)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/mixins/BulletinBoard.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.15; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | 6 | import { BulletinBoard } from "src/mixins/BulletinBoard.sol"; 7 | import { IBulletinBoardEE, AncillaryDataUpdate } from "src/interfaces/IBulletinBoard.sol"; 8 | 9 | contract BBHarness is BulletinBoard { } 10 | 11 | contract BulletinBoardTest is Test, IBulletinBoardEE { 12 | address bob = address(1); 13 | 14 | BBHarness public harness; 15 | 16 | function setUp() public { 17 | harness = new BBHarness(); 18 | } 19 | 20 | function testPostUpdate() public { 21 | bytes32 questionID = hex"1234"; 22 | bytes memory update = hex"abcd"; 23 | 24 | vm.expectEmit(true, true, true, true); 25 | emit AncillaryDataUpdated(questionID, bob, update); 26 | 27 | vm.prank(bob); 28 | harness.postUpdate(questionID, update); 29 | } 30 | 31 | function testPostUpdateMultiple() public { 32 | bytes32 questionID = hex"1234"; 33 | bytes memory update = hex"abcd"; 34 | 35 | vm.prank(bob); 36 | harness.postUpdate(questionID, update); 37 | 38 | bytes memory updateB = hex"bacd"; 39 | vm.prank(bob); 40 | harness.postUpdate(questionID, updateB); 41 | 42 | AncillaryDataUpdate[] memory updates = harness.getUpdates(questionID, bob); 43 | assertEq(updates.length, 2); 44 | 45 | // If multiple updates, GetLatestUpdate will return the most recent update only 46 | AncillaryDataUpdate memory mostRecentUpdate = harness.getLatestUpdate(questionID, bob); 47 | assertEq(mostRecentUpdate.timestamp, block.timestamp); 48 | assertEq(mostRecentUpdate.update, updateB); 49 | } 50 | 51 | function testGetUpdate() public { 52 | bytes32 questionID = hex"1234"; 53 | bytes memory update = hex"abcd"; 54 | 55 | // Get updates when none exist, returns empty list 56 | AncillaryDataUpdate[] memory updates = harness.getUpdates(questionID, bob); 57 | assertEq(updates.length, 0); 58 | 59 | // Post an ancillary data update 60 | vm.prank(bob); 61 | harness.postUpdate(questionID, update); 62 | 63 | // Get the update and assert its state 64 | updates = harness.getUpdates(questionID, bob); 65 | assertEq(updates.length, 1); 66 | AncillaryDataUpdate memory data = updates[0]; 67 | 68 | assertEq(data.update, update); 69 | assertEq(data.timestamp, block.timestamp); 70 | } 71 | 72 | function testGetLatestUpdate() public { 73 | bytes32 questionID = hex"1234"; 74 | bytes memory update = hex"abcd"; 75 | 76 | // Get latest update when none exist, returns empty struct 77 | AncillaryDataUpdate memory data = harness.getLatestUpdate(questionID, bob); 78 | assertEq(data.update, ""); 79 | assertEq(data.timestamp, 0); 80 | 81 | // Post Update 82 | vm.prank(bob); 83 | harness.postUpdate(questionID, update); 84 | 85 | data = harness.getLatestUpdate(questionID, bob); 86 | assertEq(data.update, update); 87 | assertEq(data.timestamp, block.timestamp); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@solidity-parser/parser@^0.14.3": 6 | version "0.14.3" 7 | resolved "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.3.tgz#0d627427b35a40d8521aaa933cc3df7d07bfa36f" 8 | integrity sha512-29g2SZ29HtsqA58pLCtopI1P/cPy5/UAzlcAXO6T/CNJimG6yA8kx4NaseMyJULiC+TEs02Y9/yeHzClqoA0hw== 9 | dependencies: 10 | antlr4ts "^0.5.0-alpha.4" 11 | 12 | ansi-regex@^5.0.1: 13 | version "5.0.1" 14 | resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 15 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 16 | 17 | antlr4ts@^0.5.0-alpha.4: 18 | version "0.5.0-alpha.4" 19 | resolved "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" 20 | integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== 21 | 22 | emoji-regex@^10.1.0: 23 | version "10.2.1" 24 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz#a41c330d957191efd3d9dfe6e1e8e1e9ab048b3f" 25 | integrity sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA== 26 | 27 | emoji-regex@^8.0.0: 28 | version "8.0.0" 29 | resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 30 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 31 | 32 | escape-string-regexp@^4.0.0: 33 | version "4.0.0" 34 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 35 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 36 | 37 | is-fullwidth-code-point@^3.0.0: 38 | version "3.0.0" 39 | resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 40 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 41 | 42 | lru-cache@^6.0.0: 43 | version "6.0.0" 44 | resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 45 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 46 | dependencies: 47 | yallist "^4.0.0" 48 | 49 | prettier-plugin-solidity@^1.0.0-beta.19: 50 | version "1.0.0-beta.24" 51 | resolved "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.24.tgz#67573ca87098c14f7ccff3639ddd8a4cab2a87eb" 52 | integrity sha512-6JlV5BBTWzmDSq4kZ9PTXc3eLOX7DF5HpbqmmaF+kloyUwOZbJ12hIYsUaZh2fVgZdV2t0vWcvY6qhILhlzgqg== 53 | dependencies: 54 | "@solidity-parser/parser" "^0.14.3" 55 | emoji-regex "^10.1.0" 56 | escape-string-regexp "^4.0.0" 57 | semver "^7.3.7" 58 | solidity-comments-extractor "^0.0.7" 59 | string-width "^4.2.3" 60 | 61 | prettier@^2.5.1: 62 | version "2.7.1" 63 | resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" 64 | integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== 65 | 66 | semver@^7.3.7: 67 | version "7.3.8" 68 | resolved "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" 69 | integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== 70 | dependencies: 71 | lru-cache "^6.0.0" 72 | 73 | solidity-comments-extractor@^0.0.7: 74 | version "0.0.7" 75 | resolved "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" 76 | integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== 77 | 78 | string-width@^4.2.3: 79 | version "4.2.3" 80 | resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 81 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 82 | dependencies: 83 | emoji-regex "^8.0.0" 84 | is-fullwidth-code-point "^3.0.0" 85 | strip-ansi "^6.0.1" 86 | 87 | strip-ansi@^6.0.1: 88 | version "6.0.1" 89 | resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 90 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 91 | dependencies: 92 | ansi-regex "^5.0.1" 93 | 94 | yallist@^4.0.0: 95 | version "4.0.0" 96 | resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 97 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 98 | --------------------------------------------------------------------------------