├── .cicd └── defaults.json ├── .clang-format ├── .cspell └── system-contracts-custom-dictionary.txt ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── build.yaml │ └── label_new_issues.yaml ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.sh ├── contracts ├── CMakeLists.txt ├── eosio.bios │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.bios │ │ │ └── eosio.bios.hpp │ ├── ricardian │ │ └── eosio.bios.contracts.md.in │ └── src │ │ └── eosio.bios.cpp ├── eosio.boot │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.boot │ │ │ └── eosio.boot.hpp │ ├── ricardian │ │ └── eosio.boot.contracts.md.in │ └── src │ │ └── eosio.boot.cpp ├── eosio.bpay │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.bpay │ │ │ └── eosio.bpay.hpp │ ├── ricardian │ │ └── eosio.bpay.contracts.md.in │ └── src │ │ └── eosio.bpay.cpp ├── eosio.fees │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.fees │ │ │ └── eosio.fees.hpp │ └── src │ │ └── eosio.fees.cpp ├── eosio.msig │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.msig │ │ │ └── eosio.msig.hpp │ ├── ricardian │ │ └── eosio.msig.contracts.md.in │ └── src │ │ └── eosio.msig.cpp ├── eosio.system │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.system │ │ │ ├── block_info.hpp │ │ │ ├── canon_name.hpp │ │ │ ├── eosio.system.hpp │ │ │ ├── exchange_state.hpp │ │ │ ├── limit_auth_changes.hpp │ │ │ ├── native.hpp │ │ │ ├── peer_keys.hpp │ │ │ ├── powerup.results.hpp │ │ │ └── rex.results.hpp │ ├── ricardian │ │ ├── eosio.system.clauses.md │ │ └── eosio.system.contracts.md.in │ └── src │ │ ├── block_info.cpp │ │ ├── delegate_bandwidth.cpp │ │ ├── eosio.system.cpp │ │ ├── exchange_state.cpp │ │ ├── finalizer_key.cpp │ │ ├── limit_auth_changes.cpp │ │ ├── name_bidding.cpp │ │ ├── native.cpp │ │ ├── peer_keys.cpp │ │ ├── powerup.cpp │ │ ├── powerup.results.cpp │ │ ├── producer_pay.cpp │ │ ├── rex.cpp │ │ ├── rex.results.cpp │ │ └── voting.cpp ├── eosio.token │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.token │ │ │ └── eosio.token.hpp │ ├── ricardian │ │ └── eosio.token.contracts.md.in │ └── src │ │ └── eosio.token.cpp ├── eosio.wrap │ ├── CMakeLists.txt │ ├── include │ │ └── eosio.wrap │ │ │ └── eosio.wrap.hpp │ ├── ricardian │ │ └── eosio.wrap.contracts.md.in │ └── src │ │ └── eosio.wrap.cpp ├── icons │ ├── account.png │ ├── account.svg │ ├── admin.png │ ├── admin.svg │ ├── multisig.png │ ├── multisig.svg │ ├── resource.png │ ├── resource.svg │ ├── rex.png │ ├── rex.svg │ ├── token.png │ ├── token.svg │ ├── transfer.png │ ├── transfer.svg │ ├── voting.png │ └── voting.svg └── test_contracts │ ├── CMakeLists.txt │ ├── blockinfo_tester │ ├── CMakeLists.txt │ ├── include │ │ └── blockinfo_tester │ │ │ └── blockinfo_tester.hpp │ └── src │ │ └── blockinfo_tester.cpp │ └── sendinline │ ├── CMakeLists.txt │ └── src │ └── sendinline.cpp ├── docs ├── 01_key-concepts │ ├── 01_system.md │ ├── 02_system_resources.md │ ├── 03_cpu.md │ ├── 04_net.md │ ├── 05_ram.md │ ├── 06_vote.md │ └── 07_powerup_model.md ├── 03_build-and-deploy.md ├── 04_guides │ ├── 01_upgrading-the-eosio.system-contract.md │ ├── 02_how-to-buy-ram.md │ ├── 03_how-to-stake.md │ ├── 04_how-to-vote.md │ ├── 05_how-to-create-issue-and-transfer-a-token.md │ ├── 06_how-to-sign-a-multisig-transaction-with-eosio.msig.md │ ├── 07_how-to-use-eosio.wrap.md │ └── 08_how-to-configure-the-powerup-resource-model.md └── index.md └── tests ├── CMakeLists.txt ├── contracts.hpp.in ├── eosio.bios_inst_fin_tests.cpp ├── eosio.bpay_tests.cpp ├── eosio.fees_tests.cpp ├── eosio.finalizer_key_tests.cpp ├── eosio.limitauth_tests.cpp ├── eosio.msig_tests.cpp ├── eosio.peer_keys_tests.cpp ├── eosio.powerup_tests.cpp ├── eosio.system_blockinfo_tests.cpp ├── eosio.system_ram_tests.cpp ├── eosio.system_rex_matured_tests.cpp ├── eosio.system_schedules_tests.cpp ├── eosio.system_tester.hpp ├── eosio.system_tests.cpp ├── eosio.token_tests.cpp ├── eosio.wrap_tests.cpp ├── main.cpp ├── test_contracts ├── exchange.wasm ├── old_versions │ ├── v1.2.1 │ │ ├── eosio.msig │ │ │ ├── Readme.txt │ │ │ ├── eosio.msig.abi │ │ │ └── eosio.msig.wasm │ │ └── eosio.system │ │ │ ├── README.txt │ │ │ ├── eosio.system.abi │ │ │ └── eosio.system.wasm │ └── v1.8.3 │ │ └── eosio.system │ │ ├── README.txt │ │ ├── eosio.system.abi │ │ └── eosio.system.wasm └── reject_all.wasm └── test_symbol.hpp /.cicd/defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "antelope-spring-dev":{ 3 | "target":"main", 4 | "prerelease":false 5 | }, 6 | "cdt":{ 7 | "target":"main", 8 | "prerelease":false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | ColumnLimit: 120 4 | --- 5 | Language: Cpp 6 | AccessModifierOffset: -3 7 | AlignConsecutiveAssignments: true 8 | AlignConsecutiveDeclarations: true 9 | AllowShortFunctionsOnASingleLine: All 10 | AlwaysBreakTemplateDeclarations: Yes 11 | BinPackParameters: false 12 | BraceWrapping: 13 | AfterCaseLabel: true 14 | AfterClass: true 15 | AfterControlStatement: Never 16 | AfterEnum: true 17 | AfterFunction: true 18 | AfterNamespace: false 19 | AfterStruct: true 20 | AfterUnion: true 21 | AfterExternBlock: true 22 | BeforeCatch: false 23 | BeforeElse: false 24 | IndentBraces: false 25 | SplitEmptyFunction: false 26 | SplitEmptyRecord: false 27 | SplitEmptyNamespace: false 28 | BreakBeforeBraces: Custom 29 | BreakConstructorInitializers: BeforeComma 30 | BreakInheritanceList: BeforeComma 31 | CompactNamespaces: true 32 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 33 | ConstructorInitializerIndentWidth: 1 34 | ContinuationIndentWidth: 3 35 | IndentWidth: 3 36 | PointerAlignment: Left 37 | ... 38 | -------------------------------------------------------------------------------- /.cspell/system-contracts-custom-dictionary.txt: -------------------------------------------------------------------------------- 1 | # Custom Dictionary Words 2 | abihash 3 | acnt 4 | bidname 5 | bidrefund 6 | bidrefunds 7 | bitr 8 | blockinfo 9 | bpay 10 | buyram 11 | buyrambytes 12 | buyresult 13 | buyrex 14 | byexpires 15 | byexpr 16 | byowner 17 | bytime 18 | canceldelay 19 | cfgpowerup 20 | changebw 21 | claimrewards 22 | closerex 23 | cnclrexorder 24 | cpuloan 25 | defcpuloan 26 | defnetloan 27 | defund 28 | delband 29 | delegatebw 30 | deleteauth 31 | eosio 32 | eosiosystem 33 | EOSLIB 34 | fundcpuloan 35 | fundnetloan 36 | gstate 37 | highbid 38 | ispriv 39 | isproxy 40 | lendable 41 | limitauthchg 42 | linkauth 43 | mroot 44 | mvfrsavings 45 | mvtosavings 46 | namebid 47 | namebids 48 | netloan 49 | newaccount 50 | newname 51 | nowrap 52 | oitr 53 | onblock 54 | orderresult 55 | perblock 56 | pervote 57 | pitr 58 | powerup 59 | powerupexec 60 | powup 61 | powupresult 62 | preactivate 63 | prototalvote 64 | ramcore 65 | ramfee 66 | rammarket 67 | regproducer 68 | regproxy 69 | rentcpu 70 | rentnet 71 | rentresult 72 | retbuckets 73 | rexbal 74 | rexbalance 75 | rexexec 76 | rexfund 77 | rexfunds 78 | rexorders 79 | rexpool 80 | rexqueue 81 | rexretbuckets 82 | rexretpool 83 | ritr 84 | rmvproducer 85 | runrex 86 | sellram 87 | sellresult 88 | sellrex 89 | setabi 90 | setacctcpu 91 | setacctnet 92 | setacctram 93 | setalimits 94 | setcode 95 | setinflation 96 | setpayfactor 97 | setparams 98 | setpriv 99 | setram 100 | setramrate 101 | setrex 102 | undelegate 103 | undelegatebw 104 | undelegated 105 | undelegating 106 | unlent 107 | unlinkauth 108 | unregisters 109 | unregprod 110 | unsets 111 | unstake 112 | unstaked 113 | unstakes 114 | unstaketorex 115 | unstaking 116 | updateauth 117 | updaterex 118 | updtrevision 119 | userres 120 | core.vaulta 121 | vitr 122 | vmtype 123 | vmversion 124 | votepay 125 | voteproducer 126 | voteupdate 127 | vpay 128 | wasmcfg 129 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## Change Description 5 | 6 | 7 | 8 | ## Deployment Changes 9 | - [ ] Deployment Changes 10 | 11 | 12 | 13 | 14 | ## API Changes 15 | - [ ] API Changes 16 | 17 | 18 | 19 | 20 | ## Documentation Additions 21 | - [ ] Documentation Additions 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: "Build & Test" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - "release/*" 8 | pull_request: 9 | workflow_dispatch: 10 | inputs: 11 | override-antelope-spring-dev: 12 | description: Override antelope-spring-dev target 13 | type: string 14 | override-antelope-spring-dev-prerelease: 15 | type: choice 16 | description: Override antelope-spring-dev prelease 17 | options: 18 | - default 19 | - true 20 | - false 21 | override-cdt: 22 | description: 'Override cdt target' 23 | type: string 24 | override-cdt-prerelease: 25 | type: choice 26 | description: Override cdt prelease 27 | options: 28 | - default 29 | - true 30 | - false 31 | 32 | defaults: 33 | run: 34 | shell: bash 35 | 36 | jobs: 37 | build-test: 38 | name: Build & Test 39 | runs-on: ubuntu-22.04 40 | steps: 41 | - name: Setup antelope-spring-dev & cdt versions 42 | id: versions 43 | env: 44 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 45 | run: | 46 | DEFAULTS_JSON=$(curl -sSfL $(gh api https://api.github.com/repos/${{github.repository}}/contents/.cicd/defaults.json?ref=${{github.sha}} --jq .download_url)) 47 | echo antelope-spring-dev-target=$(echo "$DEFAULTS_JSON" | jq -r '."antelope-spring-dev".target') >> $GITHUB_OUTPUT 48 | echo antelope-spring-dev-prerelease=$(echo "$DEFAULTS_JSON" | jq -r '."antelope-spring-dev".prerelease') >> $GITHUB_OUTPUT 49 | echo cdt-target=$(echo "$DEFAULTS_JSON" | jq -r '.cdt.target') >> $GITHUB_OUTPUT 50 | echo cdt-prerelease=$(echo "$DEFAULTS_JSON" | jq -r '.cdt.prerelease') >> $GITHUB_OUTPUT 51 | 52 | if [[ "${{inputs.override-antelope-spring-dev}}" != "" ]]; then 53 | echo antelope-spring-dev-target=${{inputs.override-antelope-spring-dev}} >> $GITHUB_OUTPUT 54 | fi 55 | if [[ "${{inputs.override-antelope-spring-dev-prerelease}}" == +(true|false) ]]; then 56 | echo antelope-spring-dev-prerelease=${{inputs.override-antelope-spring-dev-prerelease}} >> $GITHUB_OUTPUT 57 | fi 58 | if [[ "${{inputs.override-cdt}}" != "" ]]; then 59 | echo cdt-target=${{inputs.override-cdt}} >> $GITHUB_OUTPUT 60 | fi 61 | if [[ "${{inputs.override-cdt-prerelease}}" == +(true|false) ]]; then 62 | echo cdt-prerelease=${{inputs.override-cdt-prerelease}} >> $GITHUB_OUTPUT 63 | fi 64 | - name: Download cdt 65 | uses: AntelopeIO/asset-artifact-download-action@v3 66 | with: 67 | owner: AntelopeIO 68 | repo: cdt 69 | file: 'cdt_.*amd64.deb' 70 | target: '${{steps.versions.outputs.cdt-target}}' 71 | prereleases: ${{fromJSON(steps.versions.outputs.cdt-prerelease)}} 72 | artifact-name: cdt_ubuntu_package_amd64 73 | - name: Download antelope-spring-dev 74 | uses: AntelopeIO/asset-artifact-download-action@v3 75 | with: 76 | owner: AntelopeIO 77 | repo: spring 78 | file: 'antelope-spring-dev.*ubuntu22\.04_amd64.deb' 79 | target: '${{steps.versions.outputs.antelope-spring-dev-target}}' 80 | prereleases: ${{fromJSON(steps.versions.outputs.antelope-spring-dev-prerelease)}} 81 | artifact-name: antelope-spring-dev-ubuntu22-amd64 82 | container-package: antelope-spring-experimental-binaries 83 | - name: Install packages 84 | run: | 85 | sudo apt-get update && sudo apt-get upgrade -y 86 | sudo apt install ./*.deb 87 | sudo apt-get install cmake 88 | rm ./*.deb 89 | - uses: actions/checkout@v4 90 | with: 91 | path: src 92 | - name: Build & Test 93 | run: | 94 | cmake -S src -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=On -DSYSTEM_ENABLE_SPRING_VERSION_CHECK=Off -DSYSTEM_ENABLE_CDT_VERSION_CHECK=Off 95 | cmake --build build -- -j $(nproc) 96 | tar zcf build.tar.gz build 97 | ctest --test-dir build/tests --output-on-failure -j $(nproc) 98 | - name: Upload builddir 99 | uses: actions/upload-artifact@v4 100 | with: 101 | name: builddir 102 | path: build.tar.gz 103 | -------------------------------------------------------------------------------- /.github/workflows/label_new_issues.yaml: -------------------------------------------------------------------------------- 1 | name: Label New Issue 2 | 3 | on: 4 | issues: 5 | types: opened 6 | 7 | jobs: 8 | label_new_issue: 9 | uses: AntelopeIO/issue-project-labeler-workflow/.github/workflows/issue-project-labeler.yaml@v1 10 | with: 11 | issue-id: ${{github.event.issue.node_id}} 12 | label: triage 13 | org-project: 'ENF Engineering' 14 | project-field: Status=Todo 15 | skip-if-existing-project: true 16 | secrets: 17 | token: ${{secrets.ENFCIBOT_REPO_AND_PROJECTS}} 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build/* 35 | .DS_Store 36 | .vscode 37 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(eosio_contracts) 4 | 5 | set(VERSION_MAJOR 3) 6 | set(VERSION_MINOR 10) 7 | set(VERSION_PATCH 0) 8 | set(VERSION_SUFFIX dev) 9 | 10 | if(VERSION_SUFFIX) 11 | set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}") 12 | else() 13 | set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") 14 | endif() 15 | 16 | message(STATUS "Building system-contracts v${VERSION_FULL}") 17 | 18 | include(ExternalProject) 19 | 20 | find_package(cdt) 21 | 22 | option(SYSTEM_CONFIGURABLE_WASM_LIMITS 23 | "Enables use of the host functions activated by the CONFIGURABLE_WASM_LIMITS protocol feature" ON) 24 | 25 | option(SYSTEM_BLOCKCHAIN_PARAMETERS 26 | "Enables use of the host functions activated by the BLOCKCHAIN_PARAMETERS protocol feature" ON) 27 | 28 | option(SYSTEM_ENABLE_SPRING_VERSION_CHECK 29 | "Enables a configure-time check that the version of Spring's tester library is compatible with this project's unit tests" ON) 30 | 31 | option(SYSTEM_ENABLE_CDT_VERSION_CHECK 32 | "Enables a configure-time check that the version of CDT is compatible with this project's contracts" ON) 33 | 34 | ExternalProject_Add( 35 | contracts_project 36 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/contracts 37 | BINARY_DIR ${CMAKE_BINARY_DIR}/contracts 38 | CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release 39 | -DCMAKE_TOOLCHAIN_FILE=${CDT_ROOT}/lib/cmake/cdt/CDTWasmToolchain.cmake 40 | -DSYSTEM_CONFIGURABLE_WASM_LIMITS=${SYSTEM_CONFIGURABLE_WASM_LIMITS} 41 | -DSYSTEM_BLOCKCHAIN_PARAMETERS=${SYSTEM_BLOCKCHAIN_PARAMETERS} 42 | UPDATE_COMMAND "" 43 | PATCH_COMMAND "" 44 | TEST_COMMAND "" 45 | INSTALL_COMMAND "" 46 | BUILD_ALWAYS 1) 47 | 48 | option(BUILD_TESTS "Build unit tests" OFF) 49 | 50 | if(BUILD_TESTS) 51 | message(STATUS "Building unit tests.") 52 | add_subdirectory(tests) 53 | else() 54 | message(STATUS "Unit tests will not be built. To build unit tests, set BUILD_TESTS to ON.") 55 | endif() 56 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to system-contracts 2 | 3 | Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily: 4 | 5 | - [Reporting An Issue](#reporting-an-issue) 6 | - [Bug Reports](#bug-reports) 7 | - [Feature Requests](#feature-requests) 8 | - [Change Requests](#change-requests) 9 | - [Working on system-contracts](#working-on-system-contracts) 10 | - [Feature Branches](#feature-branches) 11 | - [Submitting Pull Requests](#submitting-pull-requests) 12 | - [Testing and Quality Assurance](#testing-and-quality-assurance) 13 | - [Conduct](#conduct) 14 | - [Contributor License & Acknowledgments](#contributor-license--acknowledgments) 15 | - [References](#references) 16 | 17 | ## Reporting An Issue 18 | 19 | If you're about to raise an issue because you think you've found a problem with system-contracts, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first. 20 | 21 | The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions: 22 | 23 | * Please **search for existing issues**. Help us keep duplicate issues to a minimum by checking to see if someone has already reported your problem or requested your idea. 24 | 25 | * Please **be civil**. Keep the discussion on topic and respect the opinions of others. See also our [Contributor Code of Conduct](#conduct). 26 | 27 | ### Bug Reports 28 | 29 | A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you! 30 | 31 | Guidelines for bug reports: 32 | 33 | 1. **Use the GitHub issue search** — check if the issue has already been 34 | reported. 35 | 36 | 1. **Check if the issue has been fixed** — look for [closed issues in the 37 | current milestone](https://github.com/VaultaFoundation/system-contracts/issues?q=is%3Aissue+is%3Aclosed) or try to reproduce it 38 | using the latest `main` branch. 39 | 40 | A good bug report shouldn't leave others needing to chase you up for more information. Be sure to include the details of your environment and relevant tests that demonstrate the failure. 41 | 42 | [Report a bug](https://github.com/VaultaFoundation/system-contracts/issues/new?title=Bug%3A) 43 | 44 | ### Feature Requests 45 | 46 | Feature requests are welcome. Before you submit one be sure to have: 47 | 48 | 1. **Use the GitHub search** and check the feature hasn't already been requested. 49 | 1. Take a moment to think about whether your idea fits with the scope and aims of the project. 50 | 1. Remember, it's up to *you* to make a strong case to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible, this means explaining the use case and why it is likely to be common. 51 | 52 | ### Change Requests 53 | 54 | Change requests cover both architectural and functional changes to how system-contracts works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to: 55 | 56 | 1. **Use the GitHub search** and check someone else didn't get there first 57 | 1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be 58 | a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there? 59 | 60 | ## Working on system-contracts 61 | 62 | Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](https://github.com/VaultaFoundation/system-contracts/labels/good%20first%20issue) label in GitHub issues. 63 | 64 | Also, please follow these guidelines when submitting code: 65 | 66 | ### Feature Branches 67 | 68 | To get it out of the way: 69 | 70 | - **[main](https://github.com/VaultaFoundation/system-contracts/tree/main)** is the development branch. All work on the next release happens here so you should generally branch off `main`. Do **NOT** use this branch for a production site. 71 | - **release/** branches contain stable releases of system-contracts. Some of these branches may be obsolete, a prerelease (release candidate), or designated as stable and ready for use in production. Generally do **NOT** use these branches to work on system-contracts' source unless you are working on a defect or change that would apply to a current stable release or release candidate. If in doubt, branch off of `main` and an system-contracts maintainer will chime in if you should switch to a release branch. 72 | 73 | ### Submitting Pull Requests 74 | 75 | Pull requests are awesome. If you're looking to raise a PR for something which doesn't have an open issue, please think carefully about [raising an issue](#reporting-an-issue) which your PR can close, especially if you're fixing a bug. This makes it more likely that there will be enough information available for your PR to be properly tested and merged. 76 | 77 | ### Testing and Quality Assurance 78 | 79 | Never underestimate just how useful quality assurance is. If you're looking to get involved with the code base and don't know where to start, checking out and testing a pull request is one of the most useful things you could do. 80 | 81 | Essentially, [check out the main branch](#working-on-system-contracts), take it for a spin, and if you find anything odd, please follow the [bug report guidelines](#bug-reports) and let us know! 82 | 83 | ## Conduct 84 | 85 | While contributing, please be respectful and constructive, so that participation in our project is a positive experience for everyone. 86 | 87 | Examples of behavior that contributes to creating a positive environment include: 88 | - Using welcoming and inclusive language 89 | - Being respectful of differing viewpoints and experiences 90 | - Gracefully accepting constructive criticism 91 | - Focusing on what is best for the community 92 | - Showing empathy towards other community members 93 | 94 | Examples of unacceptable behavior include: 95 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 96 | - Trolling, insulting/derogatory comments, and personal or political attacks 97 | - Public or private harassment 98 | - Publishing others’ private information, such as a physical or electronic address, without explicit permission 99 | - Other conduct which could reasonably be considered inappropriate in a professional setting 100 | 101 | ## Contributor License & Acknowledgments 102 | 103 | Whenever you make a contribution to this project, you license your contribution under the same terms as set out in [LICENSE](./LICENSE), and you represent and warrant that you have the right to license your contribution under those terms. Whenever you make a contribution to this project, you also certify in the terms of the Developer’s Certificate of Origin set out below: 104 | 105 | ``` 106 | Developer Certificate of Origin 107 | Version 1.1 108 | 109 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 110 | 1 Letterman Drive 111 | Suite D4700 112 | San Francisco, CA, 94129 113 | 114 | Everyone is permitted to copy and distribute verbatim copies of this 115 | license document, but changing it is not allowed. 116 | 117 | 118 | Developer's Certificate of Origin 1.1 119 | 120 | By making a contribution to this project, I certify that: 121 | 122 | (a) The contribution was created in whole or in part by me and I 123 | have the right to submit it under the open source license 124 | indicated in the file; or 125 | 126 | (b) The contribution is based upon previous work that, to the best 127 | of my knowledge, is covered under an appropriate open source 128 | license and I have the right under that license to submit that 129 | work with modifications, whether created in whole or in part 130 | by me, under the same open source license (unless I am 131 | permitted to submit under a different license), as indicated 132 | in the file; or 133 | 134 | (c) The contribution was provided directly to me by some other 135 | person who certified (a), (b) or (c) and I have not modified 136 | it. 137 | 138 | (d) I understand and agree that this project and the contribution 139 | are public and that a record of the contribution (including all 140 | personal information I submit with it, including my sign-off) is 141 | maintained indefinitely and may be redistributed consistent with 142 | this project or the open source license(s) involved. 143 | ``` 144 | 145 | ## References 146 | 147 | * Overall CONTRIB adapted from https://github.com/mathjax/MathJax/blob/master/CONTRIBUTING.md 148 | * Conduct section adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 149 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | VaultaFoundation/system-contracts 2 | eosnetworkfoundation/eos-system-contracts 3 | 4 | Copyright (c) 2021-2022 EOS Network Foundation (ENF) and its contributors. All rights reserved. 5 | This ENF software is based upon: 6 | 7 | EOSIO/eosio-contracts 8 | Copyright (c) 2017-2019 block.one and its contributors. All rights reserved. 9 | 10 | The MIT License 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | function usage() { 5 | printf "Usage: $0 OPTION... 6 | -c DIR Path to CDT installation/build directory. (Optional if using CDT installled at standard system location.) 7 | -l DIR Path to Spring build directory. Optional, but must be specified to build tests. 8 | -h Print this help menu. 9 | \\n" "$0" 1>&2 10 | exit 1 11 | } 12 | 13 | BUILD_TESTS=OFF 14 | 15 | if [ $# -ne 0 ]; then 16 | while getopts "c:l:h" opt; do 17 | case "${opt}" in 18 | c ) 19 | CDT_INSTALL_DIR=$(realpath $OPTARG) 20 | ;; 21 | l ) 22 | SPRING_BUILD_DIR=$(realpath $OPTARG) 23 | BUILD_TESTS=ON 24 | ;; 25 | h ) 26 | usage 27 | ;; 28 | ? ) 29 | echo "Invalid Option!" 1>&2 30 | usage 31 | ;; 32 | : ) 33 | echo "Invalid Option: -${OPTARG} requires an argument." 1>&2 34 | usage 35 | ;; 36 | * ) 37 | usage 38 | ;; 39 | esac 40 | done 41 | fi 42 | 43 | SPRING_DIR_CMAKE_OPTION='' 44 | 45 | if [[ "${BUILD_TESTS}" == "ON" ]]; then 46 | if [[ ! -f "$SPRING_BUILD_DIR/lib/cmake/spring/spring-config.cmake" ]]; then 47 | echo "Invalid path to Spring build directory: $SPRING_BUILD_DIR" 48 | echo "Spring build directory is required to build tests. If you do not wish to build tests, leave off the -l option." 49 | echo "Cannot proceed. Exiting..." 50 | exit 1; 51 | fi 52 | 53 | echo "Using Spring build directory at: $SPRING_BUILD_DIR" 54 | echo "" 55 | SPRING_DIR_CMAKE_OPTION="-Dspring_DIR=${SPRING_BUILD_DIR}/lib/cmake/spring" 56 | fi 57 | 58 | CDT_DIR_CMAKE_OPTION='' 59 | 60 | if [[ -z $CDT_INSTALL_DIR ]]; then 61 | echo "No CDT location was specified. Assuming installed in standard location." 62 | echo "" 63 | else 64 | if [[ ! -f "$CDT_INSTALL_DIR/lib/cmake/cdt/cdt-config.cmake" ]]; then 65 | echo "Invalid path to CDT installation/build directory: $CDT_INSTALL_DIR" 66 | echo "If CDT is installed at the standard system location, then you do not need to use the -c option." 67 | echo "Cannot proceed. Exiting..." 68 | exit 1; 69 | fi 70 | 71 | echo "Using CDT installation/build at: $CDT_INSTALL_DIR" 72 | echo "" 73 | CDT_DIR_CMAKE_OPTION="-Dcdt_DIR=${CDT_INSTALL_DIR}/lib/cmake/cdt" 74 | fi 75 | 76 | printf "\t=========== Building system-contracts ===========\n\n" 77 | RED='\033[0;31m' 78 | NC='\033[0m' 79 | CPU_CORES=$(getconf _NPROCESSORS_ONLN) 80 | mkdir -p build 81 | pushd build &> /dev/null 82 | cmake -DBUILD_TESTS=${BUILD_TESTS} ${SPRING_DIR_CMAKE_OPTION} ${CDT_DIR_CMAKE_OPTION} ../ 83 | make -j $CPU_CORES 84 | popd &> /dev/null 85 | -------------------------------------------------------------------------------- /contracts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(contracts) 4 | 5 | option(SYSTEM_CONFIGURABLE_WASM_LIMITS 6 | "Enables use of the host functions activated by the CONFIGURABLE_WASM_LIMITS protocol feature" ON) 7 | 8 | option(SYSTEM_BLOCKCHAIN_PARAMETERS 9 | "Enables use of the host functions activated by the BLOCKCHAIN_PARAMETERS protocol feature" ON) 10 | 11 | find_package(cdt) 12 | 13 | set(CDT_VERSION_MIN "4.1") 14 | set(CDT_VERSION_SOFT_MAX "4.1") 15 | # set(CDT_VERSION_HARD_MAX "") 16 | 17 | # Check the version of CDT 18 | if(SYSTEM_ENABLE_CDT_VERSION_CHECK) 19 | set(VERSION_MATCH_ERROR_MSG "") 20 | CDT_CHECK_VERSION(VERSION_OUTPUT "${CDT_VERSION}" "${CDT_VERSION_MIN}" "${CDT_VERSION_SOFT_MAX}" 21 | "${CDT_VERSION_HARD_MAX}" VERSION_MATCH_ERROR_MSG) 22 | if(VERSION_OUTPUT STREQUAL "MATCH") 23 | message(STATUS "Using CDT version ${CDT_VERSION}") 24 | elseif(VERSION_OUTPUT STREQUAL "WARN") 25 | message( 26 | WARNING 27 | "Using CDT version ${CDT_VERSION} even though it exceeds the maximum supported version of ${CDT_VERSION_SOFT_MAX}; continuing with configuration, however build may fail.\nIt is recommended to use CDT version ${CDT_VERSION_SOFT_MAX}.x" 28 | ) 29 | else() # INVALID OR MISMATCH 30 | message( 31 | FATAL_ERROR 32 | "Found CDT version ${CDT_VERSION} but it does not satisfy version requirements: ${VERSION_MATCH_ERROR_MSG}\nPlease use CDT version ${CDT_VERSION_SOFT_MAX}.x" 33 | ) 34 | endif(VERSION_OUTPUT STREQUAL "MATCH") 35 | endif() 36 | 37 | set(ICON_BASE_URL "https://raw.githubusercontent.com/eosnetworkfoundation/eos-system-contracts/main/contracts/icons") 38 | 39 | set(ACCOUNT_ICON_URI "account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f") 40 | set(ADMIN_ICON_URI "admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e") 41 | set(MULTISIG_ICON_URI "multisig.png#4fb41d3cf02d0dd2d35a29308e93c2d826ec770d6bb520db668f530764be7153") 42 | set(RESOURCE_ICON_URI "resource.png#3830f1ce8cb07f7757dbcf383b1ec1b11914ac34a1f9d8b065f07600fa9dac19") 43 | set(REX_ICON_URI "rex.png#d229837fa62a464b9c71e06060aa86179adf0b3f4e3b8c4f9702f4f4b0c340a8") 44 | set(TOKEN_ICON_URI "token.png#207ff68b0406eaa56618b08bda81d6a0954543f36adc328ab3065f31a5c5d654") 45 | set(TRANSFER_ICON_URI "transfer.png#5dfad0df72772ee1ccc155e670c1d124f5c5122f1d5027565df38b418042d1dd") 46 | set(VOTING_ICON_URI "voting.png#db28cd3db6e62d4509af3644ce7d377329482a14bb4bfaca2aa5f1400d8e8a84") 47 | 48 | add_subdirectory(eosio.bios) 49 | add_subdirectory(eosio.boot) 50 | add_subdirectory(eosio.msig) 51 | add_subdirectory(eosio.system) 52 | add_subdirectory(eosio.token) 53 | add_subdirectory(eosio.wrap) 54 | add_subdirectory(eosio.fees) 55 | add_subdirectory(eosio.bpay) 56 | 57 | add_subdirectory(test_contracts) 58 | -------------------------------------------------------------------------------- /contracts/eosio.bios/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.bios eosio.bios ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.bios.cpp) 2 | 3 | target_include_directories(eosio.bios 4 | PUBLIC 5 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 6 | 7 | set_target_properties(eosio.bios 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.bios.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.bios.contracts.md @ONLY ) 12 | 13 | target_compile_options( eosio.bios PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 14 | -------------------------------------------------------------------------------- /contracts/eosio.bios/ricardian/eosio.bios.contracts.md.in: -------------------------------------------------------------------------------- 1 |

activate

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Activate Protocol Feature 6 | summary: 'Activate protocol feature {{nowrap feature_digest}}' 7 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 8 | --- 9 | 10 | {{$action.account}} activates the protocol feature with a digest of {{feature_digest}}. 11 | 12 |

canceldelay

13 | 14 | --- 15 | spec_version: "0.2.0" 16 | title: Cancel Delayed Transaction 17 | summary: '{{nowrap canceling_auth.actor}} cancels a delayed transaction' 18 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 19 | --- 20 | 21 | {{canceling_auth.actor}} cancels the delayed transaction with id {{trx_id}}. 22 | 23 |

deleteauth

24 | 25 | --- 26 | spec_version: "0.2.0" 27 | title: Delete Account Permission 28 | summary: 'Delete the {{nowrap permission}} permission of {{nowrap account}}' 29 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 30 | --- 31 | 32 | Delete the {{permission}} permission of {{account}}. 33 | 34 |

linkauth

35 | 36 | --- 37 | spec_version: "0.2.0" 38 | title: Link Action to Permission 39 | summary: '{{nowrap account}} sets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract to {{nowrap requirement}}' 40 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 41 | --- 42 | 43 | {{account}} sets the minimum required permission for the {{#if type}}{{type}} action of the{{/if}} {{code}} contract to {{requirement}}. 44 | 45 | {{#if type}}{{else}}Any links explicitly associated to specific actions of {{code}} will take precedence.{{/if}} 46 | 47 |

newaccount

48 | 49 | --- 50 | spec_version: "0.2.0" 51 | title: Create New Account 52 | summary: '{{nowrap creator}} creates a new account with the name {{nowrap name}}' 53 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 54 | --- 55 | 56 | {{creator}} creates a new account with the name {{name}} and the following permissions: 57 | 58 | owner permission with authority: 59 | {{to_json owner}} 60 | 61 | active permission with authority: 62 | {{to_json active}} 63 | 64 |

reqactivated

65 | 66 | --- 67 | spec_version: "0.2.0" 68 | title: Assert Protocol Feature Activation 69 | summary: 'Assert that protocol feature {{nowrap feature_digest}} has been activated' 70 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 71 | --- 72 | 73 | Assert that the protocol feature with a digest of {{feature_digest}} has been activated. 74 | 75 |

reqauth

76 | 77 | --- 78 | spec_version: "0.2.0" 79 | title: Assert Authorization 80 | summary: 'Assert that authorization by {{nowrap from}} is provided' 81 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 82 | --- 83 | 84 | Assert that authorization by {{from}} is provided. 85 | 86 |

setabi

87 | 88 | --- 89 | spec_version: "0.2.0" 90 | title: Deploy Contract ABI 91 | summary: 'Deploy contract ABI on account {{nowrap account}}' 92 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 93 | --- 94 | 95 | Deploy the ABI file associated with the contract on account {{account}}. 96 | 97 |

setalimits

98 | 99 | --- 100 | spec_version: "0.2.0" 101 | title: Adjust Resource Limits of Account 102 | summary: 'Adjust resource limits of account {{nowrap account}}' 103 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 104 | --- 105 | 106 | {{$action.account}} updates {{account}}’s resource limits to have a RAM quota of {{ram_bytes}} bytes, a NET bandwidth quota of {{net_weight}} and a CPU bandwidth quota of {{cpu_weight}}. 107 | 108 |

setcode

109 | 110 | --- 111 | spec_version: "0.2.0" 112 | title: Deploy Contract Code 113 | summary: 'Deploy contract code on account {{nowrap account}}' 114 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 115 | --- 116 | 117 | Deploy compiled contract code to the account {{account}}. 118 | 119 |

setparams

120 | 121 | --- 122 | spec_version: "0.2.0" 123 | title: Set System Parameters 124 | summary: 'Set system parameters' 125 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 126 | --- 127 | 128 | {{$action.account}} sets system parameters to: 129 | {{to_json params}} 130 | 131 |

setpriv

132 | 133 | --- 134 | spec_version: "0.2.0" 135 | title: Make an Account Privileged or Unprivileged 136 | summary: '{{#if is_priv}}Make {{nowrap account}} privileged{{else}}Remove privileged status of {{nowrap account}}{{/if}}' 137 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 138 | --- 139 | 140 | {{#if is_priv}} 141 | {{$action.account}} makes {{account}} privileged. 142 | {{else}} 143 | {{$action.account}} removes privileged status of {{account}}. 144 | {{/if}} 145 | 146 |

setprods

147 | 148 | --- 149 | spec_version: "0.2.0" 150 | title: Set Block Producers 151 | summary: 'Set block producer schedule' 152 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 153 | --- 154 | 155 | {{$action.account}} proposes a block producer schedule of: 156 | {{#each schedule}} 157 | 1. {{this.producer_name}} 158 | {{/each}} 159 | 160 | The block signing authorities of each of the producers in the above schedule are listed below: 161 | {{#each schedule}} 162 | ### {{this.producer_name}} 163 | {{to_json this.authority}} 164 | {{/each}} 165 | 166 |

unlinkauth

167 | 168 | --- 169 | spec_version: "0.2.0" 170 | title: Unlink Action from Permission 171 | summary: '{{nowrap account}} unsets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract' 172 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 173 | --- 174 | 175 | {{account}} removes the association between the {{#if type}}{{type}} action of the{{/if}} {{code}} contract and its minimum required permission. 176 | 177 | {{#if type}}{{else}}This will not remove any links explicitly associated to specific actions of {{code}}.{{/if}} 178 | 179 |

updateauth

180 | 181 | --- 182 | spec_version: "0.2.0" 183 | title: Modify Account Permission 184 | summary: 'Add or update the {{nowrap permission}} permission of {{nowrap account}}' 185 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 186 | --- 187 | 188 | Modify, and create if necessary, the {{permission}} permission of {{account}} to have a parent permission of {{parent}} and the following authority: 189 | {{to_json auth}} 190 | -------------------------------------------------------------------------------- /contracts/eosio.bios/src/eosio.bios.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace eosiobios { 7 | 8 | void bios::setabi( name account, const std::vector& abi ) { 9 | abi_hash_table table(get_self(), get_self().value); 10 | auto itr = table.find( account.value ); 11 | if( itr == table.end() ) { 12 | table.emplace( account, [&]( auto& row ) { 13 | row.owner = account; 14 | row.hash = eosio::sha256(const_cast(abi.data()), abi.size()); 15 | }); 16 | } else { 17 | table.modify( itr, eosio::same_payer, [&]( auto& row ) { 18 | row.hash = eosio::sha256(const_cast(abi.data()), abi.size()); 19 | }); 20 | } 21 | } 22 | 23 | void bios::setfinalizer( const finalizer_policy& finalizer_policy ) { 24 | // exensive checks are performed to make sure setfinalizer host function 25 | // will never fail 26 | 27 | require_auth( get_self() ); 28 | 29 | check(finalizer_policy.finalizers.size() <= max_finalizers, "number of finalizers exceeds the maximum allowed"); 30 | check(finalizer_policy.finalizers.size() > 0, "require at least one finalizer"); 31 | 32 | eosio::finalizer_policy fin_policy; 33 | fin_policy.threshold = finalizer_policy.threshold; 34 | fin_policy.finalizers.reserve(finalizer_policy.finalizers.size()); 35 | 36 | const std::string pk_prefix = "PUB_BLS"; 37 | const std::string sig_prefix = "SIG_BLS"; 38 | 39 | // use raw affine format (bls_g1 is std::array) for uniqueness check 40 | struct g1_hash { 41 | std::size_t operator()(const eosio::bls_g1& g1) const { 42 | std::hash hash_func; 43 | return hash_func(g1.data()); 44 | } 45 | }; 46 | struct g1_equal { 47 | bool operator()(const eosio::bls_g1& lhs, const eosio::bls_g1& rhs) const { 48 | return std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; 49 | } 50 | }; 51 | std::unordered_set unique_finalizer_keys; 52 | 53 | uint64_t weight_sum = 0; 54 | 55 | for (const auto& f: finalizer_policy.finalizers) { 56 | check(f.description.size() <= max_finalizer_description_size, "Finalizer description greater than max allowed size"); 57 | 58 | // basic key format checks 59 | check(f.public_key.substr(0, pk_prefix.length()) == pk_prefix, "public key shoud start with PUB_BLS"); 60 | check(f.pop.substr(0, sig_prefix.length()) == sig_prefix, "proof of possession signature should start with SIG_BLS"); 61 | 62 | // check overflow 63 | check(std::numeric_limits::max() - weight_sum >= f.weight, "sum of weights causes uint64_t overflow"); 64 | weight_sum += f.weight; 65 | 66 | // decode_bls_public_key_to_g1 will fail ("check" function fails) 67 | // if the key is invalid 68 | const auto pk = eosio::decode_bls_public_key_to_g1(f.public_key); 69 | // duplicate key check 70 | check(unique_finalizer_keys.insert(pk).second, "duplicate public key"); 71 | 72 | const auto signature = eosio::decode_bls_signature_to_g2(f.pop); 73 | 74 | // proof of possession of private key check 75 | check(eosio::bls_pop_verify(pk, signature), "proof of possession failed"); 76 | 77 | std::vector pk_vector(pk.begin(), pk.end()); 78 | fin_policy.finalizers.emplace_back(eosio::finalizer_authority{f.description, f.weight, std::move(pk_vector)}); 79 | } 80 | 81 | check( weight_sum >= finalizer_policy.threshold && finalizer_policy.threshold > weight_sum / 2, 82 | "Finalizer policy threshold must be greater than half of the sum of the weights, and less than or equal to the sum of the weights"); 83 | 84 | set_finalizers(std::move(fin_policy)); 85 | } 86 | 87 | void bios::onerror( ignore, ignore> ) { 88 | check( false, "the onerror action cannot be called directly" ); 89 | } 90 | 91 | void bios::setpriv( name account, uint8_t is_priv ) { 92 | require_auth( get_self() ); 93 | set_privileged( account, is_priv ); 94 | } 95 | 96 | void bios::setalimits( name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight ) { 97 | require_auth( get_self() ); 98 | set_resource_limits( account, ram_bytes, net_weight, cpu_weight ); 99 | } 100 | 101 | void bios::setprods( const std::vector& schedule ) { 102 | require_auth( get_self() ); 103 | set_proposed_producers( schedule ); 104 | } 105 | 106 | void bios::setparams( const eosio::blockchain_parameters& params ) { 107 | require_auth( get_self() ); 108 | set_blockchain_parameters( params ); 109 | } 110 | 111 | void bios::reqauth( name from ) { 112 | require_auth( from ); 113 | } 114 | 115 | void bios::activate( const eosio::checksum256& feature_digest ) { 116 | require_auth( get_self() ); 117 | preactivate_feature( feature_digest ); 118 | } 119 | 120 | void bios::reqactivated( const eosio::checksum256& feature_digest ) { 121 | check( is_feature_activated( feature_digest ), "protocol feature is not activated" ); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /contracts/eosio.boot/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.boot eosio.boot ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.boot.cpp) 2 | 3 | target_include_directories(eosio.boot 4 | PUBLIC 5 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 6 | 7 | set_target_properties(eosio.boot 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.boot.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.boot.contracts.md @ONLY ) 12 | 13 | target_compile_options( eosio.boot PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 14 | -------------------------------------------------------------------------------- /contracts/eosio.boot/ricardian/eosio.boot.contracts.md.in: -------------------------------------------------------------------------------- 1 |

activate

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Activate Protocol Feature 6 | summary: 'Activate protocol feature {{nowrap feature_digest}}' 7 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 8 | --- 9 | 10 | {{$action.account}} activates the protocol feature with a digest of {{feature_digest}}. 11 | 12 |

canceldelay

13 | 14 | --- 15 | spec_version: "0.2.0" 16 | title: Cancel Delayed Transaction 17 | summary: '{{nowrap canceling_auth.actor}} cancels a delayed transaction' 18 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 19 | --- 20 | 21 | {{canceling_auth.actor}} cancels the delayed transaction with id {{trx_id}}. 22 | 23 |

deleteauth

24 | 25 | --- 26 | spec_version: "0.2.0" 27 | title: Delete Account Permission 28 | summary: 'Delete the {{nowrap permission}} permission of {{nowrap account}}' 29 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 30 | --- 31 | 32 | Delete the {{permission}} permission of {{account}}. 33 | 34 |

linkauth

35 | 36 | --- 37 | spec_version: "0.2.0" 38 | title: Link Action to Permission 39 | summary: '{{nowrap account}} sets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract to {{nowrap requirement}}' 40 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 41 | --- 42 | 43 | {{account}} sets the minimum required permission for the {{#if type}}{{type}} action of the{{/if}} {{code}} contract to {{requirement}}. 44 | 45 | {{#if type}}{{else}}Any links explicitly associated to specific actions of {{code}} will take precedence.{{/if}} 46 | 47 |

newaccount

48 | 49 | --- 50 | spec_version: "0.2.0" 51 | title: Create New Account 52 | summary: '{{nowrap creator}} creates a new account with the name {{nowrap name}}' 53 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 54 | --- 55 | 56 | {{creator}} creates a new account with the name {{name}} and the following permissions: 57 | 58 | owner permission with authority: 59 | {{to_json owner}} 60 | 61 | active permission with authority: 62 | {{to_json active}} 63 | 64 |

reqactivated

65 | 66 | --- 67 | spec_version: "0.2.0" 68 | title: Assert Protocol Feature Activation 69 | summary: 'Assert that protocol feature {{nowrap feature_digest}} has been activated' 70 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 71 | --- 72 | 73 | Assert that the protocol feature with a digest of {{feature_digest}} has been activated. 74 | 75 |

setabi

76 | 77 | --- 78 | spec_version: "0.2.0" 79 | title: Deploy Contract ABI 80 | summary: 'Deploy contract ABI on account {{nowrap account}}' 81 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 82 | --- 83 | 84 | Deploy the ABI file associated with the contract on account {{account}}. 85 | 86 |

setcode

87 | 88 | --- 89 | spec_version: "0.2.0" 90 | title: Deploy Contract Code 91 | summary: 'Deploy contract code on account {{nowrap account}}' 92 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 93 | --- 94 | 95 | Deploy compiled contract code to the account {{account}}. 96 | 97 |

unlinkauth

98 | 99 | --- 100 | spec_version: "0.2.0" 101 | title: Unlink Action from Permission 102 | summary: '{{nowrap account}} unsets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract' 103 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 104 | --- 105 | 106 | {{account}} removes the association between the {{#if type}}{{type}} action of the{{/if}} {{code}} contract and its minimum required permission. 107 | 108 | {{#if type}}{{else}}This will not remove any links explicitly associated to specific actions of {{code}}.{{/if}} 109 | 110 |

updateauth

111 | 112 | --- 113 | spec_version: "0.2.0" 114 | title: Modify Account Permission 115 | summary: 'Add or update the {{nowrap permission}} permission of {{nowrap account}}' 116 | icon: @ICON_BASE_URL@/@ACCOUNT_ICON_URI@ 117 | --- 118 | 119 | Modify, and create if necessary, the {{permission}} permission of {{account}} to have a parent permission of {{parent}} and the following authority: 120 | {{to_json auth}} 121 | -------------------------------------------------------------------------------- /contracts/eosio.boot/src/eosio.boot.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace eosioboot { 5 | 6 | void boot::onerror( ignore, ignore> ) { 7 | check( false, "the onerror action cannot be called directly" ); 8 | } 9 | 10 | void boot::activate( const eosio::checksum256& feature_digest ) { 11 | require_auth( get_self() ); 12 | eosio::preactivate_feature( feature_digest ); 13 | } 14 | 15 | void boot::reqactivated( const eosio::checksum256& feature_digest ) { 16 | check( eosio::is_feature_activated( feature_digest ), "protocol feature is not activated" ); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /contracts/eosio.bpay/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.bpay eosio.bpay ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.bpay.cpp) 2 | 3 | target_include_directories(eosio.bpay PUBLIC 4 | ${CMAKE_CURRENT_SOURCE_DIR}/include 5 | ${CMAKE_CURRENT_SOURCE_DIR}/../eosio.system/include 6 | ${CMAKE_CURRENT_SOURCE_DIR}/../eosio.token/include) 7 | 8 | set_target_properties(eosio.bpay 9 | PROPERTIES 10 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 11 | 12 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.bpay.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.bpay.contracts.md @ONLY ) 13 | 14 | target_compile_options( eosio.bpay PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 15 | -------------------------------------------------------------------------------- /contracts/eosio.bpay/include/eosio.bpay/eosio.bpay.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | namespace eosio { 10 | /** 11 | * The `eosio.bpay` contract handles system bpay distribution. 12 | */ 13 | class [[eosio::contract("eosio.bpay")]] bpay : public contract { 14 | public: 15 | using contract::contract; 16 | 17 | /** 18 | * ## TABLE `rewards` 19 | * 20 | * @param owner - block producer owner account 21 | * @param quantity - reward quantity in EOS (or other token) 22 | * 23 | * ### example 24 | * 25 | * ```json 26 | * [ 27 | * { 28 | * "owner": "alice", 29 | * "quantity": "8.800 EOS" 30 | * } 31 | * ] 32 | * ``` 33 | */ 34 | struct [[eosio::table("rewards")]] rewards_row { 35 | name owner; 36 | asset quantity; 37 | 38 | uint64_t primary_key() const { return owner.value; } 39 | }; 40 | typedef eosio::multi_index< "rewards"_n, rewards_row > rewards_table; 41 | 42 | /** 43 | * Claim rewards for a block producer. 44 | * 45 | * @param owner - block producer owner account 46 | */ 47 | [[eosio::action]] 48 | void claimrewards( const name owner); 49 | 50 | [[eosio::on_notify("eosio.token::transfer")]] 51 | void on_transfer( const name from, const name to, const asset quantity, const string memo ); 52 | 53 | private: 54 | }; 55 | } /// namespace eosio 56 | -------------------------------------------------------------------------------- /contracts/eosio.bpay/ricardian/eosio.bpay.contracts.md.in: -------------------------------------------------------------------------------- 1 |

claimrewards

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Claim Rewards 6 | summary: '{{nowrap owner}} claims block production rewards' 7 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 8 | --- 9 | 10 | {{owner}} claims block production rewards accumulated through network fees. 11 | -------------------------------------------------------------------------------- /contracts/eosio.bpay/src/eosio.bpay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace eosio { 4 | 5 | void bpay::claimrewards( const name owner ) { 6 | require_auth( owner ); 7 | 8 | rewards_table _rewards( get_self(), get_self().value ); 9 | 10 | const auto& row = _rewards.get( owner.value, "no rewards to claim" ); 11 | 12 | eosio::token::transfer_action transfer( "eosio.token"_n, { get_self(), "active"_n }); 13 | transfer.send( get_self(), owner, row.quantity, "producer block pay" ); 14 | 15 | _rewards.erase(row); 16 | } 17 | 18 | void bpay::on_transfer( const name from, const name to, const asset quantity, const string memo ) { 19 | if (from == get_self() || to != get_self()) { 20 | return; 21 | } 22 | 23 | // ignore eosio system incoming transfers (caused by bpay income transfers eosio => eosio.bpay => producer) 24 | if ( from == "eosio"_n) return; 25 | 26 | symbol system_symbol = eosiosystem::system_contract::get_core_symbol(); 27 | 28 | check( quantity.symbol == system_symbol, "only core token allowed" ); 29 | 30 | rewards_table _rewards( get_self(), get_self().value ); 31 | eosiosystem::producers_table _producers( "eosio"_n, "eosio"_n.value ); 32 | 33 | eosiosystem::global_state_singleton _global("eosio"_n, "eosio"_n.value); 34 | check( _global.exists(), "global state does not exist"); 35 | uint16_t producer_count = _global.get().last_producer_schedule_size; 36 | 37 | // get producer with the most votes 38 | // using `by_votes` secondary index 39 | auto idx = _producers.get_index<"prototalvote"_n>(); 40 | auto prod = idx.begin(); 41 | 42 | // get top n producers by vote, excluding inactive 43 | std::vector top_producers; 44 | while (true) { 45 | if (prod == idx.end()) break; 46 | if (prod->is_active == false) continue; 47 | 48 | top_producers.push_back(prod->owner); 49 | 50 | if (top_producers.size() == producer_count) break; 51 | 52 | prod++; 53 | } 54 | 55 | asset reward = quantity / top_producers.size(); 56 | 57 | // distribute rewards to top producers 58 | for (auto producer : top_producers) { 59 | auto row = _rewards.find( producer.value ); 60 | if (row == _rewards.end()) { 61 | _rewards.emplace( get_self(), [&](auto& row) { 62 | row.owner = producer; 63 | row.quantity = reward; 64 | }); 65 | } else { 66 | _rewards.modify(row, get_self(), [&](auto& row) { 67 | row.quantity += reward; 68 | }); 69 | } 70 | } 71 | } 72 | 73 | } /// namespace eosio 74 | -------------------------------------------------------------------------------- /contracts/eosio.fees/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.fees eosio.fees ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.fees.cpp) 2 | 3 | target_include_directories(eosio.fees PUBLIC 4 | ${CMAKE_CURRENT_SOURCE_DIR}/include 5 | ${CMAKE_CURRENT_SOURCE_DIR}/../eosio.system/include) 6 | 7 | set_target_properties(eosio.fees 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | target_compile_options( eosio.fees PUBLIC ) 12 | -------------------------------------------------------------------------------- /contracts/eosio.fees/include/eosio.fees/eosio.fees.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace eosiosystem { 10 | class system_contract; 11 | } 12 | 13 | namespace eosio { 14 | 15 | using std::string; 16 | /** 17 | * The eosio.fees smart contract facilitates the collection of transaction fees from system accounts and their subsequent distribution to the Resource Exchange (REX) pool. 18 | * 19 | * This contract serves as an essential component for inclusion in system-level unit tests. 20 | * 21 | * A comprehensive implementation of the eosio.fees contract can be accessed at Vaulta Foundation GitHub repository. 22 | * https://github.com/VaultaFoundation/eosio.fees 23 | */ 24 | class [[eosio::contract("eosio.fees")]] fees : public contract { 25 | public: 26 | using contract::contract; 27 | 28 | [[eosio::on_notify("eosio.token::transfer")]] 29 | void on_transfer( const name from, const name to, const asset quantity, const string memo ); 30 | 31 | [[eosio::action]] 32 | void noop(); 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /contracts/eosio.fees/src/eosio.fees.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace eosio { 4 | 5 | void fees::on_transfer( const name from, const name to, const asset quantity, const string memo ) 6 | { 7 | if ( to != get_self() ) { 8 | return; 9 | } 10 | if (eosiosystem::system_contract::rex_available()) { 11 | eosiosystem::system_contract::donatetorex_action donatetorex( "eosio"_n, { get_self(), "active"_n }); 12 | donatetorex.send(get_self(), quantity, memo); 13 | } 14 | } 15 | 16 | void fees::noop() 17 | { 18 | require_auth( get_self() ); 19 | } 20 | 21 | } /// namespace eosio 22 | -------------------------------------------------------------------------------- /contracts/eosio.msig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.msig eosio.msig ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.msig.cpp) 2 | 3 | target_include_directories(eosio.msig 4 | PUBLIC 5 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 6 | 7 | set_target_properties(eosio.msig 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.msig.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.msig.contracts.md @ONLY ) 12 | 13 | target_compile_options( eosio.msig PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 14 | -------------------------------------------------------------------------------- /contracts/eosio.msig/include/eosio.msig/eosio.msig.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace eosio { 9 | /** 10 | * The `eosio.msig` system contract allows for creation of proposed transactions which require authorization from a list of accounts, approval of the proposed transactions by those accounts required to approve it, and finally, it also allows the execution of the approved transactions on the blockchain. 11 | * 12 | * In short, the workflow to propose, review, approve and then executed a transaction it can be described by the following: 13 | * - first you create a transaction json file, 14 | * - then you submit this proposal to the `eosio.msig` contract, and you also insert the account permissions required to approve this proposal into the command that submits the proposal to the blockchain, 15 | * - the proposal then gets stored on the blockchain by the `eosio.msig` contract, and is accessible for review and approval to those accounts required to approve it, 16 | * - after each of the appointed accounts required to approve the proposed transactions reviews and approves it, you can execute the proposed transaction. The `eosio.msig` contract will execute it automatically, but not before validating that the transaction has not expired, it is not cancelled, and it has been signed by all the permissions in the initial proposal's required permission list. 17 | */ 18 | class [[eosio::contract("eosio.msig")]] multisig : public contract { 19 | public: 20 | using contract::contract; 21 | 22 | /** 23 | * Propose action, creates a proposal containing one transaction. 24 | * Allows an account `proposer` to make a proposal `proposal_name` which has `requested` 25 | * permission levels expected to approve the proposal, and if approved by all expected 26 | * permission levels then `trx` transaction can we executed by this proposal. 27 | * The `proposer` account is authorized and the `trx` transaction is verified if it was 28 | * authorized by the provided keys and permissions, and if the proposal name doesn’t 29 | * already exist; if all validations pass the `proposal_name` and `trx` trasanction are 30 | * saved in the proposals table and the `requested` permission levels to the 31 | * approvals table (for the `proposer` context). Storage changes are billed to `proposer`. 32 | * 33 | * @param proposer - The account proposing a transaction 34 | * @param proposal_name - The name of the proposal (should be unique for proposer) 35 | * @param requested - Permission levels expected to approve the proposal 36 | * @param trx - Proposed transaction 37 | */ 38 | [[eosio::action]] 39 | void propose(name proposer, name proposal_name, 40 | std::vector requested, ignore trx); 41 | /** 42 | * Approve action approves an existing proposal. Allows an account, the owner of `level` permission, to approve a proposal `proposal_name` 43 | * proposed by `proposer`. If the proposal's requested approval list contains the `level` 44 | * permission then the `level` permission is moved from internal `requested_approvals` list to 45 | * internal `provided_approvals` list of the proposal, thus persisting the approval for 46 | * the `proposal_name` proposal. Storage changes are billed to `proposer`. 47 | * 48 | * @param proposer - The account proposing a transaction 49 | * @param proposal_name - The name of the proposal (should be unique for proposer) 50 | * @param level - Permission level approving the transaction 51 | * @param proposal_hash - Transaction's checksum 52 | */ 53 | [[eosio::action]] 54 | void approve( name proposer, name proposal_name, permission_level level, 55 | const eosio::binary_extension& proposal_hash ); 56 | /** 57 | * Unapprove action revokes an existing proposal. This action is the reverse of the `approve` action: if all validations pass 58 | * the `level` permission is erased from internal `provided_approvals` and added to the internal 59 | * `requested_approvals` list, and thus un-approve or revoke the proposal. 60 | * 61 | * @param proposer - The account proposing a transaction 62 | * @param proposal_name - The name of the proposal (should be an existing proposal) 63 | * @param level - Permission level revoking approval for proposal 64 | */ 65 | [[eosio::action]] 66 | void unapprove( name proposer, name proposal_name, permission_level level ); 67 | /** 68 | * Cancel action cancels an existing proposal. 69 | * 70 | * @param proposer - The account proposing a transaction 71 | * @param proposal_name - The name of the proposal (should be an existing proposal) 72 | * @param canceler - The account cancelling the proposal (only the proposer can cancel an unexpired transaction, and the canceler has to be different than the proposer) 73 | * 74 | * Allows the `canceler` account to cancel the `proposal_name` proposal, created by a `proposer`, 75 | * only after time has expired on the proposed transaction. It removes corresponding entries from 76 | * internal proptable and from approval (or old approvals) tables as well. 77 | */ 78 | [[eosio::action]] 79 | void cancel( name proposer, name proposal_name, name canceler ); 80 | /** 81 | * Exec action allows an `executer` account to execute a proposal. 82 | * 83 | * Preconditions: 84 | * - `executer` has authorization, 85 | * - `proposal_name` is found in the proposals table, 86 | * - all requested approvals are received, 87 | * - proposed transaction is not expired, 88 | * - and approval accounts are not found in invalidations table. 89 | * 90 | * If all preconditions are met the transaction is executed as a deferred transaction, 91 | * and the proposal is erased from the proposals table. 92 | * 93 | * @param proposer - The account proposing a transaction 94 | * @param proposal_name - The name of the proposal (should be an existing proposal) 95 | * @param executer - The account executing the transaction 96 | */ 97 | [[eosio::action]] 98 | void exec( name proposer, name proposal_name, name executer ); 99 | /** 100 | * Invalidate action allows an `account` to invalidate itself, that is, its name is added to 101 | * the invalidations table and this table will be cross referenced when exec is performed. 102 | * 103 | * @param account - The account invalidating the transaction 104 | */ 105 | [[eosio::action]] 106 | void invalidate( name account ); 107 | 108 | using propose_action = eosio::action_wrapper<"propose"_n, &multisig::propose>; 109 | using approve_action = eosio::action_wrapper<"approve"_n, &multisig::approve>; 110 | using unapprove_action = eosio::action_wrapper<"unapprove"_n, &multisig::unapprove>; 111 | using cancel_action = eosio::action_wrapper<"cancel"_n, &multisig::cancel>; 112 | using exec_action = eosio::action_wrapper<"exec"_n, &multisig::exec>; 113 | using invalidate_action = eosio::action_wrapper<"invalidate"_n, &multisig::invalidate>; 114 | 115 | struct [[eosio::table, eosio::contract("eosio.msig")]] proposal { 116 | name proposal_name; 117 | std::vector packed_transaction; 118 | eosio::binary_extension< std::optional > earliest_exec_time; 119 | 120 | uint64_t primary_key()const { return proposal_name.value; } 121 | }; 122 | typedef eosio::multi_index< "proposal"_n, proposal > proposals; 123 | 124 | struct [[eosio::table, eosio::contract("eosio.msig")]] old_approvals_info { 125 | name proposal_name; 126 | std::vector requested_approvals; 127 | std::vector provided_approvals; 128 | uint64_t primary_key()const { return proposal_name.value; } 129 | }; 130 | typedef eosio::multi_index< "approvals"_n, old_approvals_info > old_approvals; 131 | struct approval { 132 | permission_level level; 133 | time_point time; 134 | }; 135 | 136 | struct [[eosio::table, eosio::contract("eosio.msig")]] approvals_info { 137 | uint8_t version = 1; 138 | name proposal_name; 139 | //requested approval doesn't need to contain time, but we want requested approval 140 | //to be of exactly the same size as provided approval, in this case approve/unapprove 141 | //doesn't change serialized data size. So, we use the same type. 142 | std::vector requested_approvals; 143 | std::vector provided_approvals; 144 | uint64_t primary_key()const { return proposal_name.value; } 145 | }; 146 | typedef eosio::multi_index< "approvals2"_n, approvals_info > approvals; 147 | 148 | struct [[eosio::table, eosio::contract("eosio.msig")]] invalidation { 149 | name account; 150 | time_point last_invalidation_time; 151 | 152 | uint64_t primary_key() const { return account.value; } 153 | }; 154 | 155 | typedef eosio::multi_index< "invals"_n, invalidation > invalidations; 156 | }; 157 | } /// namespace eosio 158 | -------------------------------------------------------------------------------- /contracts/eosio.msig/ricardian/eosio.msig.contracts.md.in: -------------------------------------------------------------------------------- 1 |

approve

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Approve Proposed Transaction 6 | summary: '{{nowrap level.actor}} approves the {{nowrap proposal_name}} proposal' 7 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 8 | --- 9 | 10 | {{level.actor}} approves the {{proposal_name}} proposal proposed by {{proposer}} with the {{level.permission}} permission of {{level.actor}}. 11 | 12 |

cancel

13 | 14 | --- 15 | spec_version: "0.2.0" 16 | title: Cancel Proposed Transaction 17 | summary: '{{nowrap canceler}} cancels the {{nowrap proposal_name}} proposal' 18 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 19 | --- 20 | 21 | {{canceler}} cancels the {{proposal_name}} proposal submitted by {{proposer}}. 22 | 23 |

exec

24 | 25 | --- 26 | spec_version: "0.2.0" 27 | title: Execute Proposed Transaction 28 | summary: '{{nowrap executer}} executes the {{nowrap proposal_name}} proposal' 29 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 30 | --- 31 | 32 | {{executer}} executes the {{proposal_name}} proposal submitted by {{proposer}} if the minimum required approvals for the proposal have been secured. 33 | 34 |

invalidate

35 | 36 | --- 37 | spec_version: "0.2.0" 38 | title: Invalidate All Approvals 39 | summary: '{{nowrap account}} invalidates approvals on outstanding proposals' 40 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 41 | --- 42 | 43 | {{account}} invalidates all approvals on proposals which have not yet executed. 44 | 45 |

propose

46 | 47 | --- 48 | spec_version: "0.2.0" 49 | title: Propose Transaction 50 | summary: '{{nowrap proposer}} creates the {{nowrap proposal_name}}' 51 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 52 | --- 53 | 54 | {{proposer}} creates the {{proposal_name}} proposal for the following transaction: 55 | {{to_json trx}} 56 | 57 | The proposal requests approvals from the following accounts at the specified permission levels: 58 | {{#each requested}} 59 | + {{this.permission}} permission of {{this.actor}} 60 | {{/each}} 61 | 62 | If the proposed transaction is not executed prior to {{trx.expiration}}, the proposal will automatically expire. 63 | 64 |

unapprove

65 | 66 | --- 67 | spec_version: "0.2.0" 68 | title: Unapprove Proposed Transaction 69 | summary: '{{nowrap level.actor}} revokes the approval previously provided to {{nowrap proposal_name}} proposal' 70 | icon: @ICON_BASE_URL@/@MULTISIG_ICON_URI@ 71 | --- 72 | 73 | {{level.actor}} revokes the approval previously provided at their {{level.permission}} permission level from the {{proposal_name}} proposal proposed by {{proposer}}. 74 | -------------------------------------------------------------------------------- /contracts/eosio.system/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract( 2 | eosio.system 3 | eosio.system 4 | ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.system.cpp 5 | ${CMAKE_CURRENT_SOURCE_DIR}/src/delegate_bandwidth.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/src/exchange_state.cpp 7 | ${CMAKE_CURRENT_SOURCE_DIR}/src/finalizer_key.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/src/name_bidding.cpp 9 | ${CMAKE_CURRENT_SOURCE_DIR}/src/native.cpp 10 | ${CMAKE_CURRENT_SOURCE_DIR}/src/peer_keys.cpp 11 | ${CMAKE_CURRENT_SOURCE_DIR}/src/producer_pay.cpp 12 | ${CMAKE_CURRENT_SOURCE_DIR}/src/powerup.cpp 13 | ${CMAKE_CURRENT_SOURCE_DIR}/src/rex.cpp 14 | ${CMAKE_CURRENT_SOURCE_DIR}/src/voting.cpp 15 | ${CMAKE_CURRENT_SOURCE_DIR}/src/limit_auth_changes.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/src/block_info.cpp) 17 | 18 | if(SYSTEM_CONFIGURABLE_WASM_LIMITS) 19 | target_compile_definitions(eosio.system PUBLIC SYSTEM_CONFIGURABLE_WASM_LIMITS) 20 | endif() 21 | 22 | if(SYSTEM_BLOCKCHAIN_PARAMETERS) 23 | target_compile_definitions(eosio.system PUBLIC SYSTEM_BLOCKCHAIN_PARAMETERS) 24 | endif() 25 | 26 | target_include_directories(eosio.system PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include 27 | ${CMAKE_CURRENT_SOURCE_DIR}/../eosio.token/include) 28 | 29 | set_target_properties(eosio.system PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 30 | 31 | add_contract(rex.results rex.results ${CMAKE_CURRENT_SOURCE_DIR}/src/rex.results.cpp) 32 | add_contract(powup.results powup.results ${CMAKE_CURRENT_SOURCE_DIR}/src/powerup.results.cpp) 33 | 34 | target_include_directories(rex.results PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) 35 | 36 | target_include_directories(powup.results PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) 37 | 38 | set_target_properties(rex.results PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.rex") 39 | 40 | set_target_properties(powup.results PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.powerup") 41 | 42 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.system.contracts.md.in 43 | ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.system.contracts.md @ONLY) 44 | 45 | target_compile_options(eosio.system PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian 46 | -R${CMAKE_CURRENT_BINARY_DIR}/ricardian) 47 | -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/block_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace eosiosystem::block_info { 11 | 12 | static constexpr uint32_t rolling_window_size = 10; 13 | 14 | /** 15 | * The blockinfo table holds a rolling window of records containing information for recent blocks. 16 | * 17 | * Each record stores the height and timestamp of the correspond block. 18 | * A record is added for a new block through the onblock action. 19 | * The onblock action also erases up to two old records at a time in an attempt to keep the table consisting of only 20 | * records for blocks going back a particular block height difference backward from the most recent block. 21 | * Currently that block height difference is hardcoded to 10. 22 | */ 23 | struct [[eosio::table, eosio::contract("eosio.system")]] block_info_record 24 | { 25 | uint8_t version = 0; 26 | uint32_t block_height; 27 | eosio::time_point block_timestamp; 28 | 29 | uint64_t primary_key() const { return block_height; } 30 | 31 | EOSLIB_SERIALIZE(block_info_record, (version)(block_height)(block_timestamp)) 32 | }; 33 | 34 | using block_info_table = eosio::multi_index<"blockinfo"_n, block_info_record>; 35 | 36 | struct block_batch_info 37 | { 38 | uint32_t batch_start_height; 39 | eosio::time_point batch_start_timestamp; 40 | uint32_t batch_current_end_height; 41 | eosio::time_point batch_current_end_timestamp; 42 | }; 43 | 44 | struct latest_block_batch_info_result 45 | { 46 | enum error_code_enum : uint32_t 47 | { 48 | no_error, 49 | invalid_input, 50 | unsupported_version, 51 | insufficient_data 52 | }; 53 | 54 | std::optional result; 55 | error_code_enum error_code = no_error; 56 | }; 57 | 58 | /** 59 | * Get information on the latest block batch. 60 | * 61 | * A block batch is a contiguous range of blocks of a particular size. 62 | * A sequence of blocks can be partitioned into a sequence of block batches, where all except for perhaps the last batch 63 | * in the sequence have the same size. The last batch in the sequence can have a smaller size if the 64 | * blocks of the blockchain that would complete that batch have not yet been generated or recorded. 65 | * 66 | * This function enables the caller to specify a particular partitioning of the sequence of blocks into a sequence of 67 | * block batches of a particular non-zero size (`batch_size`) and then isolates the last block batch in that sequence 68 | * and returns the information about that latest block batch if possible. The partitioning will ensure that 69 | * `batch_start_height_offset` will be equal to the starting block height of exactly one of block batches in the 70 | * sequence. 71 | * 72 | * The information about the latest block batch is the same data captured in `block_batch_info`. 73 | * Particularly, it returns the height and timestamp of starting and ending blocks within that latest block batch. 74 | * Note that the range spanning from the start to end block of the latest block batch may be less than batch_size 75 | * because latest block batch may be incomplete. 76 | * Also, it is possible for the record capturing info for the starting block to not exist in the blockinfo table. This 77 | * can either be due to the records being erased as they fall out of the rolling window or, in rare cases, due to gaps 78 | * in block info records due to failures of the onblock action. In such a case, this function will be unable to return a 79 | * `block_batch_info` and will instead be forced to return the `insufficient_data` error code. 80 | * Furthermore, if `batch_start_height_offset` is greater than the height of the latest block for which 81 | * information is recorded in the blockinfo table, there will be no latest block batch identified for the function to 82 | * return information about and so it will again be forced to return the `insufficient_data` error code instead. 83 | */ 84 | latest_block_batch_info_result get_latest_block_batch_info(uint32_t batch_start_height_offset, 85 | uint32_t batch_size, 86 | eosio::name system_account_name = "eosio"_n) 87 | { 88 | latest_block_batch_info_result result; 89 | 90 | if (batch_size == 0) { 91 | result.error_code = latest_block_batch_info_result::invalid_input; 92 | return result; 93 | } 94 | 95 | block_info_table t(system_account_name, 0); 96 | 97 | // Find information on latest block recorded in the blockinfo table. 98 | 99 | if (t.cbegin() == t.cend()) { 100 | // The blockinfo table is empty. 101 | result.error_code = latest_block_batch_info_result::insufficient_data; 102 | return result; 103 | } 104 | 105 | auto latest_block_info_itr = --t.cend(); 106 | 107 | if (latest_block_info_itr->version != 0) { 108 | // Compiled code for this function within the calling contract has not been updated to support new version of 109 | // the blockinfo table. 110 | result.error_code = latest_block_batch_info_result::unsupported_version; 111 | return result; 112 | } 113 | 114 | uint32_t latest_block_batch_end_height = latest_block_info_itr->block_height; 115 | 116 | if (latest_block_batch_end_height < batch_start_height_offset) { 117 | // Caller asking for a block batch that has not even begun to be recorded yet. 118 | result.error_code = latest_block_batch_info_result::insufficient_data; 119 | return result; 120 | } 121 | 122 | // Calculate height for the starting block of the latest block batch. 123 | 124 | uint32_t latest_block_batch_start_height = 125 | latest_block_batch_end_height - ((latest_block_batch_end_height - batch_start_height_offset) % batch_size); 126 | 127 | // Note: 1 <= (latest_block_batch_end_height - latest_block_batch_start_height + 1) <= batch_size 128 | 129 | if (latest_block_batch_start_height == latest_block_batch_end_height) { 130 | // When batch_size == 1, this function effectively simplifies to just returning the info of the latest recorded 131 | // block. In that case, the start block and the end block of the batch are the same and there is no need for 132 | // another lookup. So shortcut the rest of the process and return a successful result immediately. 133 | result.result.emplace(block_batch_info{ 134 | .batch_start_height = latest_block_batch_start_height, 135 | .batch_start_timestamp = latest_block_info_itr->block_timestamp, 136 | .batch_current_end_height = latest_block_batch_end_height, 137 | .batch_current_end_timestamp = latest_block_info_itr->block_timestamp, 138 | }); 139 | return result; 140 | } 141 | 142 | // Find information on start block of the latest block batch recorded in the blockinfo table. 143 | 144 | auto start_block_info_itr = t.find(latest_block_batch_start_height); 145 | if (start_block_info_itr == t.cend() || start_block_info_itr->block_height != latest_block_batch_start_height) { 146 | // Record for information on start block of the latest block batch could not be found in blockinfo table. 147 | // This is either because of: 148 | // * a gap in recording info due to a failed onblock action; 149 | // * a requested start block that was processed by onblock prior to deployment of the system contract code 150 | // introducing the blockinfo table; 151 | // * or, most likely, because the record for the requested start block was pruned from the blockinfo table as 152 | // it fell out of the rolling window. 153 | result.error_code = latest_block_batch_info_result::insufficient_data; 154 | return result; 155 | } 156 | 157 | if (start_block_info_itr->version != 0) { 158 | // Compiled code for this function within the calling contract has not been updated to support new version of 159 | // the blockinfo table. 160 | result.error_code = latest_block_batch_info_result::unsupported_version; 161 | return result; 162 | } 163 | 164 | // Successfully return block_batch_info for the found latest block batch in its current state. 165 | 166 | result.result.emplace(block_batch_info{ 167 | .batch_start_height = latest_block_batch_start_height, 168 | .batch_start_timestamp = start_block_info_itr->block_timestamp, 169 | .batch_current_end_height = latest_block_batch_end_height, 170 | .batch_current_end_timestamp = latest_block_info_itr->block_timestamp, 171 | }); 172 | return result; 173 | } 174 | 175 | } // namespace eosiosystem::block_info 176 | -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/canon_name.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace eosiosystem { 5 | 6 | // ------------------------------------------------------------------------------------------- 7 | struct canon_name_t 8 | { 9 | uint64_t _value; // all significant characters are shifted to the least significant position 10 | uint64_t _size; // number of significant characters 11 | 12 | uint64_t mask() const { return (1ull << (_size * 5)) - 1; } 13 | uint64_t size() const { return _size; } 14 | bool valid() const { return _size != 0; } 15 | 16 | // starts from the end, so n[0] is the last significant character of the name 17 | uint64_t operator[](uint64_t i) const { return (_value >> (5 * i)) & 0x1F; } 18 | 19 | canon_name_t(name n) { 20 | uint64_t v = n.value; 21 | auto num_zeros = std::countr_zero(v); 22 | if ((num_zeros < 4) || (num_zeros == 64)) { // 13th char must be zero, and pattern should not be empty 23 | _size = 0; // zero size denotes an invalid pattern 24 | } else { 25 | uint64_t shift = 4 + ((num_zeros - 4) / 5) * 5; 26 | _value = v >> shift; 27 | auto sig_bits = 64 - shift; 28 | _size = sig_bits / 5; 29 | } 30 | } 31 | 32 | // returns true if account_name ends with the same characters as `this`, preceded by a `.` (zero) character 33 | bool is_suffix_of(canon_name_t account_name) const { 34 | assert(valid()); 35 | if (size() > account_name.size()) 36 | return false; 37 | 38 | if (((_value ^ account_name._value) & mask()) != 0) 39 | return false; 40 | 41 | // pattern matches the end of account_name. To be a suffix it has to either be the same length (i.e. exact match), 42 | // or be preceded by a dot in account_name 43 | return (size() == account_name.size()) || (account_name[size()] == 0); 44 | } 45 | 46 | bool found_in(canon_name_t account_name) const { 47 | assert(valid()); 48 | if (size() > account_name.size()) 49 | return false; 50 | 51 | auto sz = size(); 52 | size_t diff = account_name.size() - sz + 1; 53 | for (size_t i = 0; i < diff; ++i) 54 | if (((_value ^ (account_name._value >> (5 * i))) & mask()) == 0) 55 | return true; 56 | return false; 57 | } 58 | }; 59 | 60 | // ------------------------------------------------------------------------------------------- 61 | static inline bool name_allowed(name account, name patt) 62 | { 63 | canon_name_t pattern(patt); 64 | canon_name_t account_name(account); 65 | 66 | if (!pattern.valid()) 67 | return true; // ignore invalid patterns 68 | 69 | if (pattern.is_suffix_of(account_name)) 70 | return true; 71 | if (pattern.found_in(account_name)) 72 | return false; 73 | return true; 74 | } 75 | 76 | } // namespace eosiosystem -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/exchange_state.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace eosiosystem { 7 | 8 | using eosio::asset; 9 | using eosio::symbol; 10 | 11 | /** 12 | * Uses Bancor math to create a 50/50 relay between two asset types. 13 | * 14 | * The state of the bancor exchange is entirely contained within this struct. 15 | * There are no external side effects associated with using this API. 16 | */ 17 | struct [[eosio::table, eosio::contract("eosio.system")]] exchange_state { 18 | asset supply; 19 | 20 | struct connector { 21 | asset balance; 22 | double weight = .5; 23 | 24 | EOSLIB_SERIALIZE( connector, (balance)(weight) ) 25 | }; 26 | 27 | connector base; 28 | connector quote; 29 | 30 | uint64_t primary_key()const { return supply.symbol.raw(); } 31 | 32 | asset convert_to_exchange( connector& reserve, const asset& payment ); 33 | asset convert_from_exchange( connector& reserve, const asset& tokens ); 34 | asset convert( const asset& from, const symbol& to ); 35 | asset direct_convert( const asset& from, const symbol& to ); 36 | 37 | static int64_t get_bancor_output( int64_t inp_reserve, 38 | int64_t out_reserve, 39 | int64_t inp ); 40 | static int64_t get_bancor_input( int64_t out_reserve, 41 | int64_t inp_reserve, 42 | int64_t out ); 43 | 44 | EOSLIB_SERIALIZE( exchange_state, (supply)(base)(quote) ) 45 | }; 46 | 47 | typedef eosio::multi_index< "rammarket"_n, exchange_state > rammarket; 48 | } /// namespace eosiosystem 49 | -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/limit_auth_changes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace eosiosystem { 6 | using eosio::name; 7 | 8 | struct [[eosio::table("limitauthchg"),eosio::contract("eosio.system")]] limit_auth_change { 9 | uint8_t version = 0; 10 | name account; 11 | std::vector allow_perms; 12 | std::vector disallow_perms; 13 | 14 | uint64_t primary_key() const { return account.value; } 15 | 16 | EOSLIB_SERIALIZE(limit_auth_change, (version)(account)(allow_perms)(disallow_perms)) 17 | }; 18 | 19 | typedef eosio::multi_index<"limitauthchg"_n, limit_auth_change> limit_auth_change_table; 20 | } // namespace eosiosystem 21 | -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/peer_keys.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | namespace eosiosystem { 11 | 12 | using eosio::name; 13 | using eosio::public_key; 14 | 15 | // ------------------------------------------------------------------------------------------------- 16 | // ------------------------------------------------------------------------------------------------- 17 | struct [[eosio::table("peerkeys"), eosio::contract("eosio.system")]] peer_key { 18 | struct v0_data { 19 | std::optional pubkey; // peer key for network message authentication 20 | EOSLIB_SERIALIZE(v0_data, (pubkey)) 21 | }; 22 | 23 | name account; 24 | std::variant data; 25 | 26 | uint64_t primary_key() const { return account.value; } 27 | 28 | void set_public_key(const public_key& key) { data = v0_data{key}; } 29 | const std::optional& get_public_key() const { 30 | return std::visit([](auto& v) -> const std::optional& { return v.pubkey; }, data); 31 | } 32 | void update_row() {} 33 | void init_row(name n) { *this = peer_key{n, v0_data{}}; } 34 | }; 35 | 36 | // ------------------------------------------------------------------------------------------------- 37 | // ------------------------------------------------------------------------------------------------- 38 | typedef eosio::multi_index<"peerkeys"_n, peer_key> peer_keys_table; 39 | 40 | // ------------------------------------------------------------------------------------------------- 41 | // ------------------------------------------------------------------------------------------------- 42 | struct [[eosio::contract("eosio.system")]] peer_keys : public eosio::contract { 43 | 44 | peer_keys(name s, name code, eosio::datastream ds) 45 | : eosio::contract(s, code, ds) {} 46 | 47 | struct peerkeys_t { 48 | name producer_name; 49 | std::optional peer_key; 50 | 51 | EOSLIB_SERIALIZE(peerkeys_t, (producer_name)(peer_key)) 52 | }; 53 | 54 | using getpeerkeys_res_t = std::vector; 55 | 56 | /** 57 | * Action to register a public key for a proposer or finalizer name. 58 | * This key will be used to validate a network peer's identity. 59 | * A proposer or finalizer can only have have one public key registered at a time. 60 | * If a key is already registered for `proposer_finalizer_name`, and `regpeerkey` is 61 | * called with a different key, the new key replaces the previous one in `peer_keys_table` 62 | */ 63 | [[eosio::action]] 64 | void regpeerkey(const name& proposer_finalizer_name, const public_key& key); 65 | 66 | /** 67 | * Action to delete a public key for a proposer or finalizer name. 68 | * 69 | * An existing public key for a given account can be changed by calling `regpeerkey` again. 70 | */ 71 | [[eosio::action]] 72 | void delpeerkey(const name& proposer_finalizer_name, const public_key& key); 73 | 74 | /** 75 | * Returns a list of up to 50 top producers (active *and* non-active, in votes rank order), 76 | * along with their peer public key if it was registered via the regpeerkey action. 77 | */ 78 | [[eosio::action]] 79 | getpeerkeys_res_t getpeerkeys(); 80 | 81 | }; 82 | 83 | } // namespace eosiosystem -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/powerup.results.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using eosio::action_wrapper; 8 | using eosio::asset; 9 | using eosio::name; 10 | 11 | /** 12 | * The action `powupresult` is a no-op. 13 | * It is added as an inline convenience action to `powerup` reservation. 14 | * This inline convenience action does not have any effect, however, 15 | * its data includes the result of the parent action and appears in its trace. 16 | */ 17 | class [[eosio::contract("powup.results")]] powup_results : eosio::contract { 18 | public: 19 | 20 | using eosio::contract::contract; 21 | 22 | /** 23 | * powupresult action. 24 | * 25 | * @param fee - powerup fee amount 26 | * @param powup_net - amount of powup NET tokens 27 | * @param powup_cpu - amount of powup CPU tokens 28 | */ 29 | [[eosio::action]] 30 | void powupresult( const asset& fee, const int64_t powup_net, const int64_t powup_cpu ); 31 | 32 | using powupresult_action = action_wrapper<"powupresult"_n, &powup_results::powupresult>; 33 | }; 34 | -------------------------------------------------------------------------------- /contracts/eosio.system/include/eosio.system/rex.results.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using eosio::action_wrapper; 8 | using eosio::asset; 9 | using eosio::name; 10 | 11 | /** 12 | * The actions `buyresult`, `sellresult`, `rentresult`, and `orderresult` of `rex.results` are all no-ops. 13 | * They are added as inline convenience actions to `rentnet`, `rentcpu`, `buyrex`, `unstaketorex`, and `sellrex`. 14 | * An inline convenience action does not have any effect, however, 15 | * its data includes the result of the parent action and appears in its trace. 16 | */ 17 | class [[eosio::contract("rex.results")]] rex_results : eosio::contract { 18 | public: 19 | 20 | using eosio::contract::contract; 21 | 22 | /** 23 | * Buyresult action. 24 | * 25 | * @param rex_received - amount of tokens used in buy order 26 | */ 27 | [[eosio::action]] 28 | void buyresult( const asset& rex_received ); 29 | 30 | /** 31 | * Sellresult action. 32 | * 33 | * @param proceeds - amount of tokens used in sell order 34 | */ 35 | [[eosio::action]] 36 | void sellresult( const asset& proceeds ); 37 | 38 | /** 39 | * Orderresult action. 40 | * 41 | * @param owner - the owner of the order 42 | * @param proceeds - amount of tokens used in order 43 | */ 44 | [[eosio::action]] 45 | void orderresult( const name& owner, const asset& proceeds ); 46 | 47 | /** 48 | * Rentresult action. 49 | * 50 | * @param rented_tokens - amount of rented tokens 51 | */ 52 | [[eosio::action]] 53 | void rentresult( const asset& rented_tokens ); 54 | 55 | using buyresult_action = action_wrapper<"buyresult"_n, &rex_results::buyresult>; 56 | using sellresult_action = action_wrapper<"sellresult"_n, &rex_results::sellresult>; 57 | using orderresult_action = action_wrapper<"orderresult"_n, &rex_results::orderresult>; 58 | using rentresult_action = action_wrapper<"rentresult"_n, &rex_results::rentresult>; 59 | }; 60 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/block_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace { 5 | 6 | inline uint32_t block_height_from_id(const eosio::checksum256& block_id) 7 | { 8 | auto arr = block_id.extract_as_byte_array(); 9 | // 32-bit block height is encoded in big endian as the sequence of bytes: arr[0], arr[1], arr[2], arr[3] 10 | return ((arr[0] << 0x18) | (arr[1] << 0x10) | (arr[2] << 0x08) | arr[3]); 11 | } 12 | 13 | } // namespace 14 | 15 | namespace eosiosystem { 16 | 17 | void system_contract::add_to_blockinfo_table(const eosio::checksum256& previous_block_id, 18 | const eosio::block_timestamp timestamp) const 19 | { 20 | const uint32_t new_block_height = block_height_from_id(previous_block_id) + 1; 21 | const auto new_block_timestamp = static_cast(timestamp); 22 | 23 | block_info::block_info_table t(get_self(), 0); 24 | 25 | if (block_info::rolling_window_size > 0) { 26 | // Add new entry to blockinfo table for the new block. 27 | t.emplace(get_self(), [&](block_info::block_info_record& r) { 28 | r.block_height = new_block_height; 29 | r.block_timestamp = new_block_timestamp; 30 | }); 31 | } 32 | 33 | // Erase up to two entries that have fallen out of the rolling window. 34 | 35 | const uint32_t last_prunable_block_height = 36 | std::max(new_block_height, block_info::rolling_window_size) - block_info::rolling_window_size; 37 | 38 | int count = 2; 39 | for (auto itr = t.begin(), end = t.end(); // 40 | itr != end && itr->block_height <= last_prunable_block_height && 0 < count; // 41 | --count) // 42 | { 43 | itr = t.erase(itr); 44 | } 45 | } 46 | 47 | } // namespace eosiosystem -------------------------------------------------------------------------------- /contracts/eosio.system/src/exchange_state.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace eosiosystem { 8 | 9 | using eosio::check; 10 | 11 | asset exchange_state::convert_to_exchange( connector& reserve, const asset& payment ) 12 | { 13 | const double S0 = supply.amount; 14 | const double R0 = reserve.balance.amount; 15 | const double dR = payment.amount; 16 | const double F = reserve.weight; 17 | 18 | double dS = S0 * ( std::pow(1. + dR / R0, F) - 1. ); 19 | if ( dS < 0 ) dS = 0; // rounding errors 20 | reserve.balance += payment; 21 | supply.amount += int64_t(dS); 22 | return asset( int64_t(dS), supply.symbol ); 23 | } 24 | 25 | asset exchange_state::convert_from_exchange( connector& reserve, const asset& tokens ) 26 | { 27 | const double R0 = reserve.balance.amount; 28 | const double S0 = supply.amount; 29 | const double dS = -tokens.amount; // dS < 0, tokens are subtracted from supply 30 | const double Fi = double(1) / reserve.weight; 31 | 32 | double dR = R0 * ( std::pow(1. + dS / S0, Fi) - 1. ); // dR < 0 since dS < 0 33 | if ( dR > 0 ) dR = 0; // rounding errors 34 | reserve.balance.amount -= int64_t(-dR); 35 | supply -= tokens; 36 | return asset( int64_t(-dR), reserve.balance.symbol ); 37 | } 38 | 39 | asset exchange_state::convert( const asset& from, const symbol& to ) 40 | { 41 | const auto& sell_symbol = from.symbol; 42 | const auto& base_symbol = base.balance.symbol; 43 | const auto& quote_symbol = quote.balance.symbol; 44 | check( sell_symbol != to, "cannot convert to the same symbol" ); 45 | 46 | asset out( 0, to ); 47 | if ( sell_symbol == base_symbol && to == quote_symbol ) { 48 | const asset tmp = convert_to_exchange( base, from ); 49 | out = convert_from_exchange( quote, tmp ); 50 | } else if ( sell_symbol == quote_symbol && to == base_symbol ) { 51 | const asset tmp = convert_to_exchange( quote, from ); 52 | out = convert_from_exchange( base, tmp ); 53 | } else { 54 | check( false, "invalid conversion" ); 55 | } 56 | return out; 57 | } 58 | 59 | asset exchange_state::direct_convert( const asset& from, const symbol& to ) 60 | { 61 | const auto& sell_symbol = from.symbol; 62 | const auto& base_symbol = base.balance.symbol; 63 | const auto& quote_symbol = quote.balance.symbol; 64 | check( sell_symbol != to, "cannot convert to the same symbol" ); 65 | 66 | asset out( 0, to ); 67 | if ( sell_symbol == base_symbol && to == quote_symbol ) { 68 | out.amount = get_bancor_output( base.balance.amount, quote.balance.amount, from.amount ); 69 | base.balance += from; 70 | quote.balance -= out; 71 | } else if ( sell_symbol == quote_symbol && to == base_symbol ) { 72 | out.amount = get_bancor_output( quote.balance.amount, base.balance.amount, from.amount ); 73 | quote.balance += from; 74 | base.balance -= out; 75 | } else { 76 | check( false, "invalid conversion" ); 77 | } 78 | return out; 79 | } 80 | 81 | int64_t exchange_state::get_bancor_output( int64_t inp_reserve, 82 | int64_t out_reserve, 83 | int64_t inp ) 84 | { 85 | const double ib = inp_reserve; 86 | const double ob = out_reserve; 87 | const double in = inp; 88 | 89 | int64_t out = int64_t( (in * ob) / (ib + in) ); 90 | 91 | if ( out < 0 ) out = 0; 92 | 93 | return out; 94 | } 95 | 96 | int64_t exchange_state::get_bancor_input( int64_t out_reserve, 97 | int64_t inp_reserve, 98 | int64_t out ) 99 | { 100 | const double ob = out_reserve; 101 | const double ib = inp_reserve; 102 | 103 | int64_t inp = (ib * out) / (ob - out); 104 | 105 | if ( inp < 0 ) inp = 0; 106 | 107 | return inp; 108 | } 109 | 110 | } /// namespace eosiosystem 111 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/limit_auth_changes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace eosiosystem { 5 | 6 | void system_contract::limitauthchg(const name& account, const std::vector& allow_perms, 7 | const std::vector& disallow_perms) { 8 | limit_auth_change_table table(get_self(), get_self().value); 9 | require_auth(account); 10 | eosio::check(allow_perms.empty() || disallow_perms.empty(), "either allow_perms or disallow_perms must be empty"); 11 | eosio::check(allow_perms.empty() || 12 | std::find(allow_perms.begin(), allow_perms.end(), "owner"_n) != allow_perms.end(), 13 | "allow_perms does not contain owner"); 14 | eosio::check(disallow_perms.empty() || 15 | std::find(disallow_perms.begin(), disallow_perms.end(), "owner"_n) == disallow_perms.end(), 16 | "disallow_perms contains owner"); 17 | auto it = table.find(account.value); 18 | if(!allow_perms.empty() || !disallow_perms.empty()) { 19 | if(it == table.end()) { 20 | table.emplace(account, [&](auto& row){ 21 | row.account = account; 22 | row.allow_perms = allow_perms; 23 | row.disallow_perms = disallow_perms; 24 | }); 25 | } else { 26 | table.modify(it, account, [&](auto& row){ 27 | row.allow_perms = allow_perms; 28 | row.disallow_perms = disallow_perms; 29 | }); 30 | } 31 | } else { 32 | if(it != table.end()) 33 | table.erase(it); 34 | } 35 | } 36 | 37 | void check_auth_change(name contract, name account, const binary_extension& authorized_by) { 38 | name by(authorized_by.has_value() ? authorized_by.value().value : 0); 39 | if(by.value) 40 | eosio::require_auth({account, by}); 41 | limit_auth_change_table table(contract, contract.value); 42 | auto it = table.find(account.value); 43 | if(it == table.end()) 44 | return; 45 | eosio::check(by.value, "authorized_by is required for this account"); 46 | if(!it->allow_perms.empty()) 47 | eosio::check( 48 | std::find(it->allow_perms.begin(), it->allow_perms.end(), by) != it->allow_perms.end(), 49 | "authorized_by does not appear in allow_perms"); 50 | else 51 | eosio::check( 52 | std::find(it->disallow_perms.begin(), it->disallow_perms.end(), by) == it->disallow_perms.end(), 53 | "authorized_by appears in disallow_perms"); 54 | } 55 | 56 | } // namespace eosiosystem 57 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/name_bidding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | namespace eosiosystem { 7 | 8 | using eosio::current_time_point; 9 | using eosio::token; 10 | 11 | void system_contract::bidname( const name& bidder, const name& newname, const asset& bid ) { 12 | require_auth( bidder ); 13 | check( newname.suffix() == newname, "you can only bid on top-level suffix" ); 14 | 15 | check( (bool)newname, "the empty name is not a valid account name to bid on" ); 16 | check( (newname.value & 0xFull) == 0, "13 character names are not valid account names to bid on" ); 17 | check( (newname.value & 0x1F0ull) == 0, "accounts with 12 character names and no dots can be created without bidding required" ); 18 | check( !is_account( newname ), "account already exists" ); 19 | check( bid.symbol == core_symbol(), "asset must be system token" ); 20 | check( bid.amount > 0, "insufficient bid" ); 21 | token::transfer_action transfer_act{ token_account, { {bidder, active_permission} } }; 22 | transfer_act.send( bidder, names_account, bid, std::string("bid name ")+ newname.to_string() ); 23 | name_bid_table bids(get_self(), get_self().value); 24 | print( name{bidder}, " bid ", bid, " on ", name{newname}, "\n" ); 25 | auto current = bids.find( newname.value ); 26 | if( current == bids.end() ) { 27 | bids.emplace( bidder, [&]( auto& b ) { 28 | b.newname = newname; 29 | b.high_bidder = bidder; 30 | b.high_bid = bid.amount; 31 | b.last_bid_time = current_time_point(); 32 | }); 33 | } else { 34 | check( current->high_bid > 0, "this auction has already closed" ); 35 | check( bid.amount - current->high_bid > (current->high_bid / 10), "must increase bid by 10%" ); 36 | check( current->high_bidder != bidder, "account is already highest bidder" ); 37 | 38 | bid_refund_table refunds_table(get_self(), newname.value); 39 | 40 | auto it = refunds_table.find( current->high_bidder.value ); 41 | if ( it != refunds_table.end() ) { 42 | refunds_table.modify( it, same_payer, [&](auto& r) { 43 | r.amount += asset( current->high_bid, core_symbol() ); 44 | }); 45 | } else { 46 | refunds_table.emplace( bidder, [&](auto& r) { 47 | r.bidder = current->high_bidder; 48 | r.amount = asset( current->high_bid, core_symbol() ); 49 | }); 50 | } 51 | 52 | bids.modify( current, bidder, [&]( auto& b ) { 53 | b.high_bidder = bidder; 54 | b.high_bid = bid.amount; 55 | b.last_bid_time = current_time_point(); 56 | }); 57 | } 58 | } 59 | 60 | void system_contract::bidrefund( const name& bidder, const name& newname ) { 61 | bid_refund_table refunds_table(get_self(), newname.value); 62 | auto it = refunds_table.find( bidder.value ); 63 | check( it != refunds_table.end(), "refund not found" ); 64 | 65 | token::transfer_action transfer_act{ token_account, { {names_account, active_permission}, {bidder, active_permission} } }; 66 | transfer_act.send( names_account, bidder, asset(it->amount), std::string("refund bid on name ")+(name{newname}).to_string() ); 67 | refunds_table.erase( it ); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/native.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | namespace eosiosystem { 6 | 7 | void native::onerror( ignore, ignore> ) { 8 | eosio::check( false, "the onerror action cannot be called directly" ); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/peer_keys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | namespace eosiosystem { 8 | 9 | void peer_keys::regpeerkey(const name& proposer_finalizer_name, const public_key& key) { 10 | require_auth(proposer_finalizer_name); 11 | peer_keys_table peer_keys_table(get_self(), get_self().value); 12 | check(!std::holds_alternative(key), "webauthn keys not allowed in regpeerkey action"); 13 | 14 | auto peers_itr = peer_keys_table.find(proposer_finalizer_name.value); 15 | if (peers_itr == peer_keys_table.end()) { 16 | peer_keys_table.emplace(proposer_finalizer_name, [&](auto& row) { 17 | row.init_row(proposer_finalizer_name); 18 | row.set_public_key(key); 19 | }); 20 | } else { 21 | const auto& prev_key = peers_itr->get_public_key(); 22 | check(!prev_key || *prev_key != key, "Provided key is the same as currently stored one"); 23 | peer_keys_table.modify(peers_itr, same_payer, [&](auto& row) { 24 | row.update_row(); 25 | row.set_public_key(key); 26 | }); 27 | } 28 | } 29 | 30 | void peer_keys::delpeerkey(const name& proposer_finalizer_name, const public_key& key) { 31 | require_auth(proposer_finalizer_name); 32 | peer_keys_table peer_keys_table(get_self(), get_self().value); 33 | 34 | auto peers_itr = peer_keys_table.find(proposer_finalizer_name.value); 35 | check(peers_itr != peer_keys_table.end(), "Key not present for name: " + proposer_finalizer_name.to_string()); 36 | const auto& prev_key = peers_itr->get_public_key(); 37 | check(prev_key && *prev_key == key, "Current key does not match the provided one"); 38 | peer_keys_table.erase(peers_itr); 39 | } 40 | 41 | peer_keys::getpeerkeys_res_t peer_keys::getpeerkeys() { 42 | peer_keys_table peer_keys_table(get_self(), get_self().value); 43 | producers_table producers(get_self(), get_self().value); 44 | constexpr size_t max_return = 50; 45 | 46 | getpeerkeys_res_t resp; 47 | resp.reserve(max_return); 48 | 49 | double vote_threshold = 0; // vote_threshold will always be >= 0 50 | 51 | auto add_peer = [&](auto it) { 52 | auto peers_itr = peer_keys_table.find(it->owner.value); 53 | if (peers_itr == peer_keys_table.end()) 54 | resp.push_back(peerkeys_t{it->owner, {}}); 55 | else 56 | resp.push_back(peerkeys_t{it->owner, peers_itr->get_public_key()}); 57 | 58 | // once 21 producers have been selected, we will only consider producers 59 | // that have more than 50% of the votes of the 21st selected producer. 60 | // --------------------------------------------------------------------- 61 | if (resp.size() == 21) 62 | vote_threshold = it->total_votes * 0.5; 63 | }; 64 | 65 | auto idx = producers.get_index<"prototalvote"_n>(); 66 | 67 | auto it = idx.cbegin(); 68 | auto rit = idx.cend(); 69 | if (it == rit) 70 | return resp; 71 | else 72 | --rit; 73 | 74 | // 1. Consider both active and non-active producers. as a non-active producer can be 75 | // reactivated at any time. 76 | // 2. Once we have selected 21 producers, the threshold of votes required to be selected 77 | // increases from `> 0` to `> 50% of the votes that the 21st selected producer has`. 78 | // 3. We iterate from both ends, as non-active producers are indexed at the end (their 79 | // vote total is negated for the index computation). As a consequence, the highest 80 | // voted non-active producer will be the last entry of our index. 81 | // -------------------------------------------------------------------------------------- 82 | bool last_one = false; 83 | do { 84 | // at this point, `it` and `rit` both point to a valid `producer_info` (possibly the same) 85 | assert(it <= rit); 86 | assert(vote_threshold >= 0); 87 | assert(it->total_votes >= 0 && rit->total_votes >= 0); 88 | last_one = (it == rit); 89 | if (rit->total_votes > std::max(vote_threshold, it->total_votes)) { 90 | add_peer(rit); 91 | assert(it != rit); // Should always be satisfied since `rit->total_votes > it->total_votes` 92 | --rit; // safe because `rit` cannot point to the first entry of the index. 93 | } else if (it->total_votes > vote_threshold) { 94 | add_peer(it); 95 | ++it; 96 | } else { 97 | // `total_votes <= threshold` on both ends of the index, exit the loop. 98 | break; 99 | } 100 | } while (!last_one && resp.size() < max_return); 101 | 102 | return resp; 103 | } 104 | 105 | } // namespace eosiosystem 106 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/powerup.results.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void powup_results::powupresult( const asset& fee, const int64_t powup_net_weight, const int64_t powup_cpu_weight ) { } 4 | 5 | extern "C" void apply( uint64_t, uint64_t, uint64_t ) { } 6 | -------------------------------------------------------------------------------- /contracts/eosio.system/src/rex.results.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void rex_results::buyresult( const asset& rex_received ) { } 4 | 5 | void rex_results::sellresult( const asset& proceeds ) { } 6 | 7 | void rex_results::orderresult( const name& owner, const asset& proceeds ) { } 8 | 9 | void rex_results::rentresult( const asset& rented_tokens ) { } 10 | 11 | extern "C" void apply( uint64_t, uint64_t, uint64_t ) { } 12 | -------------------------------------------------------------------------------- /contracts/eosio.token/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.token eosio.token ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.token.cpp) 2 | 3 | target_include_directories(eosio.token 4 | PUBLIC 5 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 6 | 7 | set_target_properties(eosio.token 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.token.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.token.contracts.md @ONLY ) 12 | 13 | target_compile_options( eosio.token PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 14 | -------------------------------------------------------------------------------- /contracts/eosio.token/ricardian/eosio.token.contracts.md.in: -------------------------------------------------------------------------------- 1 |

close

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Close Token Balance 6 | summary: 'Close {{nowrap owner}}’s zero quantity balance' 7 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 8 | --- 9 | 10 | {{owner}} agrees to close their zero quantity balance for the {{symbol_to_symbol_code symbol}} token. 11 | 12 | RAM will be refunded to the RAM payer of the {{symbol_to_symbol_code symbol}} token balance for {{owner}}. 13 | 14 |

create

15 | 16 | --- 17 | spec_version: "0.2.0" 18 | title: Create New Token 19 | summary: 'Create a new token' 20 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 21 | --- 22 | 23 | {{$action.account}} agrees to create a new token with symbol {{asset_to_symbol_code maximum_supply}} to be managed by {{issuer}}. 24 | 25 | This action will not result any any tokens being issued into circulation. 26 | 27 | {{issuer}} will be allowed to issue tokens into circulation, up to a maximum supply of {{maximum_supply}}. 28 | 29 | RAM will deducted from {{$action.account}}’s resources to create the necessary records. 30 | 31 |

setmaxsupply

32 | 33 | --- 34 | spec_version: "0.2.0" 35 | title: Set Max Supply 36 | summary: 'Set max supply for token' 37 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 38 | --- 39 | 40 | {{issuer}} will be allowed to issue tokens into circulation, up to a maximum supply of {{maximum_supply}}. 41 | 42 | This action will not result any any tokens being issued into circulation. 43 | 44 |

issue

45 | 46 | --- 47 | spec_version: "0.2.0" 48 | title: Issue Tokens into Circulation 49 | summary: 'Issue {{nowrap quantity}} into circulation and transfer into {{nowrap to}}’s account' 50 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 51 | --- 52 | 53 | The token manager agrees to issue {{quantity}} into circulation, and transfer it into {{to}}’s account. 54 | 55 | {{#if memo}}There is a memo attached to the transfer stating: 56 | {{memo}} 57 | {{/if}} 58 | 59 | If {{to}} does not have a balance for {{asset_to_symbol_code quantity}}, or the token manager does not have a balance for {{asset_to_symbol_code quantity}}, the token manager will be designated as the RAM payer of the {{asset_to_symbol_code quantity}} token balance for {{to}}. As a result, RAM will be deducted from the token manager’s resources to create the necessary records. 60 | 61 | This action does not allow the total quantity to exceed the max allowed supply of the token. 62 | 63 |

issuefixed

64 | 65 | --- 66 | spec_version: "0.2.0" 67 | title: Issue Fixed Supply of Tokens into Circulation 68 | summary: 'Issue up to {{nowrap supply}} supply into circulation and transfer into {{nowrap to}}’s account' 69 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 70 | --- 71 | 72 | The token manager agrees to issue tokens up to {{supply}} fixed supply into circulation, and transfer it into {{to}}’s account. 73 | 74 | {{#if memo}}There is a memo attached to the transfer stating: 75 | {{memo}} 76 | {{/if}} 77 | 78 | If {{to}} does not have a balance for {{asset_to_symbol_code quantity}}, or the token manager does not have a balance for {{asset_to_symbol_code quantity}}, the token manager will be designated as the RAM payer of the {{asset_to_symbol_code quantity}} token balance for {{to}}. As a result, RAM will be deducted from the token manager’s resources to create the necessary records. 79 | 80 | This action does not allow the total quantity to exceed the max allowed supply of the token. 81 | 82 |

open

83 | 84 | --- 85 | spec_version: "0.2.0" 86 | title: Open Token Balance 87 | summary: 'Open a zero quantity balance for {{nowrap owner}}' 88 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 89 | --- 90 | 91 | {{ram_payer}} agrees to establish a zero quantity balance for {{owner}} for the {{symbol_to_symbol_code symbol}} token. 92 | 93 | If {{owner}} does not have a balance for {{symbol_to_symbol_code symbol}}, {{ram_payer}} will be designated as the RAM payer of the {{symbol_to_symbol_code symbol}} token balance for {{owner}}. As a result, RAM will be deducted from {{ram_payer}}’s resources to create the necessary records. 94 | 95 |

retire

96 | 97 | --- 98 | spec_version: "0.2.0" 99 | title: Remove Tokens from Circulation 100 | summary: 'Remove {{nowrap quantity}} from circulation' 101 | icon: @ICON_BASE_URL@/@TOKEN_ICON_URI@ 102 | --- 103 | 104 | The token manager agrees to remove {{quantity}} from circulation, taken from their own account. 105 | 106 | {{#if memo}} There is a memo attached to the action stating: 107 | {{memo}} 108 | {{/if}} 109 | 110 |

transfer

111 | 112 | --- 113 | spec_version: "0.2.0" 114 | title: Transfer Tokens 115 | summary: 'Send {{nowrap quantity}} from {{nowrap from}} to {{nowrap to}}' 116 | icon: @ICON_BASE_URL@/@TRANSFER_ICON_URI@ 117 | --- 118 | 119 | {{from}} agrees to send {{quantity}} to {{to}}. 120 | 121 | {{#if memo}}There is a memo attached to the transfer stating: 122 | {{memo}} 123 | {{/if}} 124 | 125 | If {{from}} is not already the RAM payer of their {{asset_to_symbol_code quantity}} token balance, {{from}} will be designated as such. As a result, RAM will be deducted from {{from}}’s resources to refund the original RAM payer. 126 | 127 | If {{to}} does not have a balance for {{asset_to_symbol_code quantity}}, {{from}} will be designated as the RAM payer of the {{asset_to_symbol_code quantity}} token balance for {{to}}. As a result, RAM will be deducted from {{from}}’s resources to create the necessary records. -------------------------------------------------------------------------------- /contracts/eosio.token/src/eosio.token.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace eosio { 4 | 5 | void token::create( const name& issuer, 6 | const asset& maximum_supply ) 7 | { 8 | require_auth( get_self() ); 9 | 10 | auto sym = maximum_supply.symbol; 11 | check( maximum_supply.is_valid(), "invalid supply"); 12 | check( maximum_supply.amount > 0, "max-supply must be positive"); 13 | 14 | stats statstable( get_self(), sym.code().raw() ); 15 | auto existing = statstable.find( sym.code().raw() ); 16 | check( existing == statstable.end(), "token with symbol already exists" ); 17 | 18 | statstable.emplace( get_self(), [&]( auto& s ) { 19 | s.supply.symbol = maximum_supply.symbol; 20 | s.max_supply = maximum_supply; 21 | s.issuer = issuer; 22 | }); 23 | } 24 | 25 | 26 | void token::issue( const name& to, const asset& quantity, const string& memo ) 27 | { 28 | auto sym = quantity.symbol; 29 | check( sym.is_valid(), "invalid symbol name" ); 30 | check( memo.size() <= 256, "memo has more than 256 bytes" ); 31 | 32 | stats statstable( get_self(), sym.code().raw() ); 33 | auto existing = statstable.find( sym.code().raw() ); 34 | check( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); 35 | const auto& st = *existing; 36 | check( to == st.issuer, "tokens can only be issued to issuer account" ); 37 | 38 | require_auth( st.issuer ); 39 | check( quantity.is_valid(), "invalid quantity" ); 40 | check( quantity.amount > 0, "must issue positive quantity" ); 41 | 42 | check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 43 | check( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); 44 | 45 | statstable.modify( st, same_payer, [&]( auto& s ) { 46 | s.supply += quantity; 47 | }); 48 | 49 | add_balance( st.issuer, quantity, st.issuer ); 50 | } 51 | 52 | void token::issuefixed( const name& to, const asset& supply, const string& memo ) 53 | { 54 | const asset circulating_supply = get_supply( get_self(), supply.symbol.code() ); 55 | check( circulating_supply.symbol == supply.symbol, "symbol precision mismatch" ); 56 | const asset quantity = supply - circulating_supply; 57 | issue( to, quantity, memo ); 58 | } 59 | 60 | void token::setmaxsupply( const name& issuer, const asset& maximum_supply ) 61 | { 62 | auto sym = maximum_supply.symbol; 63 | check( maximum_supply.is_valid(), "invalid supply"); 64 | check( maximum_supply.amount > 0, "max-supply must be positive"); 65 | 66 | stats statstable( get_self(), sym.code().raw() ); 67 | auto & st = statstable.get( sym.code().raw(), "token supply does not exist" ); 68 | check( issuer == st.issuer, "only issuer can set token maximum supply" ); 69 | require_auth( st.issuer ); 70 | 71 | check( maximum_supply.symbol == st.supply.symbol, "symbol precision mismatch" ); 72 | check( maximum_supply.amount >= st.supply.amount, "max supply is less than available supply"); 73 | 74 | statstable.modify( st, same_payer, [&]( auto& s ) { 75 | s.max_supply = maximum_supply; 76 | }); 77 | } 78 | 79 | void token::retire( const asset& quantity, const string& memo ) 80 | { 81 | auto sym = quantity.symbol; 82 | check( sym.is_valid(), "invalid symbol name" ); 83 | check( memo.size() <= 256, "memo has more than 256 bytes" ); 84 | 85 | stats statstable( get_self(), sym.code().raw() ); 86 | auto existing = statstable.find( sym.code().raw() ); 87 | check( existing != statstable.end(), "token with symbol does not exist" ); 88 | const auto& st = *existing; 89 | 90 | require_auth( st.issuer ); 91 | check( quantity.is_valid(), "invalid quantity" ); 92 | check( quantity.amount > 0, "must retire positive quantity" ); 93 | 94 | check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 95 | 96 | statstable.modify( st, same_payer, [&]( auto& s ) { 97 | s.supply -= quantity; 98 | }); 99 | 100 | sub_balance( st.issuer, quantity ); 101 | } 102 | 103 | void token::transfer( const name& from, 104 | const name& to, 105 | const asset& quantity, 106 | const string& memo ) 107 | { 108 | check( from != to, "cannot transfer to self" ); 109 | require_auth( from ); 110 | check( is_account( to ), "to account does not exist"); 111 | auto sym = quantity.symbol.code(); 112 | stats statstable( get_self(), sym.raw() ); 113 | const auto& st = statstable.get( sym.raw() ); 114 | 115 | require_recipient( from ); 116 | require_recipient( to ); 117 | 118 | check( quantity.is_valid(), "invalid quantity" ); 119 | check( quantity.amount > 0, "must transfer positive quantity" ); 120 | check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 121 | check( memo.size() <= 256, "memo has more than 256 bytes" ); 122 | 123 | auto payer = has_auth( to ) ? to : from; 124 | 125 | sub_balance( from, quantity ); 126 | add_balance( to, quantity, payer ); 127 | } 128 | 129 | void token::sub_balance( const name& owner, const asset& value ) { 130 | accounts from_acnts( get_self(), owner.value ); 131 | 132 | const auto& from = from_acnts.get( value.symbol.code().raw(), "no balance object found" ); 133 | check( from.balance.amount >= value.amount, "overdrawn balance" ); 134 | 135 | from_acnts.modify( from, owner, [&]( auto& a ) { 136 | a.balance -= value; 137 | }); 138 | } 139 | 140 | void token::add_balance( const name& owner, const asset& value, const name& ram_payer ) 141 | { 142 | accounts to_acnts( get_self(), owner.value ); 143 | auto to = to_acnts.find( value.symbol.code().raw() ); 144 | if( to == to_acnts.end() ) { 145 | to_acnts.emplace( ram_payer, [&]( auto& a ){ 146 | a.balance = value; 147 | }); 148 | } else { 149 | to_acnts.modify( to, same_payer, [&]( auto& a ) { 150 | a.balance += value; 151 | }); 152 | } 153 | } 154 | 155 | void token::open( const name& owner, const symbol& symbol, const name& ram_payer ) 156 | { 157 | require_auth( ram_payer ); 158 | 159 | check( is_account( owner ), "owner account does not exist" ); 160 | 161 | auto sym_code_raw = symbol.code().raw(); 162 | stats statstable( get_self(), sym_code_raw ); 163 | const auto& st = statstable.get( sym_code_raw, "symbol does not exist" ); 164 | check( st.supply.symbol == symbol, "symbol precision mismatch" ); 165 | 166 | accounts acnts( get_self(), owner.value ); 167 | auto it = acnts.find( sym_code_raw ); 168 | if( it == acnts.end() ) { 169 | acnts.emplace( ram_payer, [&]( auto& a ){ 170 | a.balance = asset{0, symbol}; 171 | }); 172 | } 173 | } 174 | 175 | void token::close( const name& owner, const symbol& symbol ) 176 | { 177 | require_auth( owner ); 178 | accounts acnts( get_self(), owner.value ); 179 | auto it = acnts.find( symbol.code().raw() ); 180 | check( it != acnts.end(), "Balance row already deleted or never existed. Action won't have any effect." ); 181 | check( it->balance.amount == 0, "Cannot close because the balance is not zero." ); 182 | acnts.erase( it ); 183 | } 184 | 185 | } /// namespace eosio -------------------------------------------------------------------------------- /contracts/eosio.wrap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(eosio.wrap eosio.wrap ${CMAKE_CURRENT_SOURCE_DIR}/src/eosio.wrap.cpp) 2 | 3 | target_include_directories(eosio.wrap 4 | PUBLIC 5 | ${CMAKE_CURRENT_SOURCE_DIR}/include) 6 | 7 | set_target_properties(eosio.wrap 8 | PROPERTIES 9 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 10 | 11 | configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ricardian/eosio.wrap.contracts.md.in ${CMAKE_CURRENT_BINARY_DIR}/ricardian/eosio.wrap.contracts.md @ONLY ) 12 | 13 | target_compile_options( eosio.wrap PUBLIC -R${CMAKE_CURRENT_SOURCE_DIR}/ricardian -R${CMAKE_CURRENT_BINARY_DIR}/ricardian ) 14 | -------------------------------------------------------------------------------- /contracts/eosio.wrap/include/eosio.wrap/eosio.wrap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace eosio { 8 | /** 9 | * The `eosio.wrap` system contract allows block producers to bypass authorization checks or run privileged actions with 15/21 producer approval and thus simplifies block producers superuser actions. It also makes these actions easier to audit. 10 | * 11 | * It does not give block producers any additional powers or privileges that do not already exist within the EOSIO based blockchains. As it is implemented, in an EOSIO based blockchain, 15/21 block producers can change an account's permissions or modify an account's contract code if they decided it is beneficial for the blockchain and community. However, the current method is opaque and leaves undesirable side effects on specific system accounts, and thus the `eosio.wrap `contract solves this matter by providing an easier method of executing important governance actions. 12 | * 13 | * The only action implemented by the `eosio.wrap` system contract is the `exec` action. This action allows for execution of a transaction, which is passed to the `exec` method in the form of a packed transaction in json format via the 'trx' parameter and the `executer` account that executes the transaction. The same `executer` account will also be used to pay the RAM and CPU fees needed to execute the transaction. 14 | */ 15 | class [[eosio::contract("eosio.wrap")]] wrap : public contract { 16 | public: 17 | using contract::contract; 18 | 19 | /** 20 | * Execute action. 21 | * 22 | * Execute a transaction while bypassing regular authorization checks. 23 | * 24 | * Preconditions: 25 | * - Requires authorization of eosio.wrap which needs to be a privileged account. 26 | * 27 | * Postconditions: 28 | * - Deferred transaction RAM usage is billed to 'executer' * 29 | * 30 | * @param executer - account executing the transaction, 31 | * @param trx - the transaction to be executed. 32 | */ 33 | [[eosio::action]] 34 | void exec( ignore executer, ignore trx ); 35 | 36 | using exec_action = eosio::action_wrapper<"exec"_n, &wrap::exec>; 37 | }; 38 | } /// namespace eosio 39 | -------------------------------------------------------------------------------- /contracts/eosio.wrap/ricardian/eosio.wrap.contracts.md.in: -------------------------------------------------------------------------------- 1 |

exec

2 | 3 | --- 4 | spec_version: "0.2.0" 5 | title: Privileged Execute 6 | summary: '{{nowrap executer}} executes a transaction while bypassing authority checks' 7 | icon: @ICON_BASE_URL@/@ADMIN_ICON_URI@ 8 | --- 9 | 10 | {{executer}} executes the following transaction while bypassing authority checks: 11 | {{to_json trx}} 12 | 13 | {{$action.account}} must also authorize this action. 14 | -------------------------------------------------------------------------------- /contracts/eosio.wrap/src/eosio.wrap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace eosio { 4 | 5 | void wrap::exec( ignore, ignore ) { 6 | require_auth( get_self() ); 7 | 8 | name executer; 9 | _ds >> executer; 10 | 11 | require_auth( executer ); 12 | 13 | transaction_header trx_header; 14 | std::vector context_free_actions; 15 | std::vector actions; 16 | _ds >> trx_header; 17 | _ds >> context_free_actions; 18 | check( context_free_actions.empty(), "not allowed to `exec` a transaction with context-free actions" ); 19 | _ds >> actions; 20 | 21 | for (const auto& act : actions) { 22 | act.send(); 23 | } 24 | } 25 | 26 | } /// namespace eosio 27 | -------------------------------------------------------------------------------- /contracts/icons/account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/account.png -------------------------------------------------------------------------------- /contracts/icons/account.svg: -------------------------------------------------------------------------------- 1 | Account -------------------------------------------------------------------------------- /contracts/icons/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/admin.png -------------------------------------------------------------------------------- /contracts/icons/admin.svg: -------------------------------------------------------------------------------- 1 | Admin -------------------------------------------------------------------------------- /contracts/icons/multisig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/multisig.png -------------------------------------------------------------------------------- /contracts/icons/multisig.svg: -------------------------------------------------------------------------------- 1 | Multi Sig -------------------------------------------------------------------------------- /contracts/icons/resource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/resource.png -------------------------------------------------------------------------------- /contracts/icons/resource.svg: -------------------------------------------------------------------------------- 1 | Resource -------------------------------------------------------------------------------- /contracts/icons/rex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/rex.png -------------------------------------------------------------------------------- /contracts/icons/rex.svg: -------------------------------------------------------------------------------- 1 | Rex -------------------------------------------------------------------------------- /contracts/icons/token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/token.png -------------------------------------------------------------------------------- /contracts/icons/token.svg: -------------------------------------------------------------------------------- 1 | Token_1 -------------------------------------------------------------------------------- /contracts/icons/transfer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/transfer.png -------------------------------------------------------------------------------- /contracts/icons/transfer.svg: -------------------------------------------------------------------------------- 1 | Transfer_1 -------------------------------------------------------------------------------- /contracts/icons/voting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/contracts/icons/voting.png -------------------------------------------------------------------------------- /contracts/icons/voting.svg: -------------------------------------------------------------------------------- 1 | Voting_1 -------------------------------------------------------------------------------- /contracts/test_contracts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(blockinfo_tester) 2 | add_subdirectory(sendinline) -------------------------------------------------------------------------------- /contracts/test_contracts/blockinfo_tester/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(blockinfo_tester ${CMAKE_CURRENT_SOURCE_DIR}/src/blockinfo_tester.cpp) 2 | 3 | target_include_directories(blockinfo_tester PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include 4 | "$") 5 | 6 | set_target_properties(blockinfo_tester PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") 7 | 8 | target_compile_options(blockinfo_tester PUBLIC --no-abigen) 9 | -------------------------------------------------------------------------------- /contracts/test_contracts/blockinfo_tester/include/blockinfo_tester/blockinfo_tester.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef TEST_INCLUDE 4 | 5 | #include 6 | #include 7 | 8 | #else 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace system_contracts::testing::test_contracts::blockinfo_tester { 22 | 23 | #ifdef TEST_INCLUDE 24 | 25 | using time_point = fc::time_point; 26 | using varint = fc::unsigned_int; 27 | 28 | #else 29 | 30 | using time_point = eosio::time_point; 31 | using varint = eosio::unsigned_int; 32 | 33 | #endif 34 | 35 | /** 36 | * @brief Input data structure for `get_latest_block_batch_info` RPC 37 | * 38 | * @details Use this struct as the input for a call to the `get_latest_block_batch_info` RPC. That call will return the 39 | * result as the `latest_block_batch_info_result` struct. 40 | */ 41 | struct get_latest_block_batch_info 42 | { 43 | uint32_t batch_start_height_offset; 44 | uint32_t batch_size; 45 | }; 46 | 47 | #ifdef TEST_INCLUDE 48 | 49 | struct block_batch_info 50 | { 51 | uint32_t batch_start_height; 52 | time_point batch_start_timestamp; 53 | uint32_t batch_current_end_height; 54 | time_point batch_current_end_timestamp; 55 | }; 56 | 57 | #else 58 | 59 | using eosiosystem::block_info::block_batch_info; 60 | 61 | #endif 62 | 63 | /** 64 | * @brief Output data structure for `get_latest_block_batch_info` RPC 65 | */ 66 | struct latest_block_batch_info_result 67 | { 68 | enum error_code_enum : uint32_t 69 | { 70 | no_error, 71 | invalid_input, 72 | unsupported_version, 73 | insufficient_data 74 | }; 75 | 76 | std::optional result; 77 | varint error_code = no_error; 78 | 79 | bool has_error() const { return !(error_code.value == no_error && result.has_value()); } 80 | 81 | error_code_enum get_error() const { return static_cast(error_code.value); } 82 | 83 | #ifndef TEST_INCLUDE 84 | 85 | EOSLIB_SERIALIZE(latest_block_batch_info_result, (result)(error_code)) 86 | 87 | #endif 88 | }; 89 | 90 | using input_type = std::variant; 91 | 92 | using output_type = std::variant; 93 | 94 | } // namespace system_contracts::testing::test_contracts::blockinfo_tester 95 | 96 | #ifdef TEST_INCLUDE 97 | 98 | FC_REFLECT(system_contracts::testing::test_contracts::blockinfo_tester::get_latest_block_batch_info, 99 | (batch_start_height_offset)(batch_size)) 100 | FC_REFLECT(system_contracts::testing::test_contracts::blockinfo_tester::block_batch_info, 101 | (batch_start_height)(batch_start_timestamp)(batch_current_end_height)(batch_current_end_timestamp)) 102 | FC_REFLECT_ENUM( 103 | system_contracts::testing::test_contracts::blockinfo_tester::latest_block_batch_info_result::error_code_enum, 104 | (no_error)(invalid_input)(unsupported_version)(insufficient_data)) 105 | FC_REFLECT(system_contracts::testing::test_contracts::blockinfo_tester::latest_block_batch_info_result, 106 | (result)(error_code)) 107 | 108 | #endif -------------------------------------------------------------------------------- /contracts/test_contracts/blockinfo_tester/src/blockinfo_tester.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace { 13 | 14 | namespace block_info = eosiosystem::block_info; 15 | 16 | } 17 | namespace system_contracts::testing::test_contracts::blockinfo_tester { 18 | 19 | auto process(get_latest_block_batch_info request) -> latest_block_batch_info_result 20 | { 21 | latest_block_batch_info_result response; 22 | 23 | block_info::latest_block_batch_info_result res = 24 | block_info::get_latest_block_batch_info(request.batch_start_height_offset, request.batch_size); 25 | 26 | response.result = std::move(res.result); 27 | response.error_code.value = static_cast(res.error_code); 28 | 29 | eosio::print("get_latest_block_batch_info: response error_code = ", response.error_code.value, "\n"); 30 | if (response.result.has_value()) { 31 | const auto& result = *response.result; 32 | eosio::print("get_latest_block_batch_info: response result:\n"); 33 | eosio::print(" batch_start_height = ", result.batch_start_height, "\n"); 34 | eosio::print(" batch_current_end_height = ", result.batch_current_end_height, "\n"); 35 | } 36 | 37 | return response; 38 | } 39 | 40 | output_type process_call(input_type input) 41 | { 42 | return std::visit([](auto&& arg) -> output_type { return process(std::move(arg)); }, std::move(input)); 43 | } 44 | 45 | } // namespace system_contracts::testing::test_contracts::blockinfo_tester 46 | 47 | [[eosio::wasm_entry]] extern "C" void apply(uint64_t receiver, uint64_t code, uint64_t action) 48 | { 49 | namespace ns = system_contracts::testing::test_contracts::blockinfo_tester; 50 | 51 | if (receiver == code) { 52 | if (action == "call"_n.value) { 53 | ns::input_type input; 54 | 55 | { 56 | std::vector buffer; 57 | buffer.resize(eosio::action_data_size()); 58 | eosio::read_action_data(buffer.data(), buffer.size()); 59 | 60 | eosio::datastream input_ds(static_cast(buffer.data()), buffer.size()); 61 | input_ds >> input; 62 | } 63 | 64 | auto output = ns::process_call(std::move(input)); 65 | static_assert(std::is_same_v); 66 | 67 | { 68 | eosio::action return_action; 69 | return_action.account = eosio::name{receiver}; 70 | return_action.name = "return"_n; 71 | 72 | eosio::datastream output_size_ds; 73 | output_size_ds << output; 74 | return_action.data.resize(output_size_ds.tellp()); 75 | eosio::datastream output_ds(static_cast(return_action.data.data()), 76 | return_action.data.size()); 77 | output_ds << output; 78 | 79 | return_action.send(); 80 | } 81 | } else if (action == "abort"_n.value) { 82 | eosio::check(false, 0ull); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /contracts/test_contracts/sendinline/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_contract(sendinline sendinline ${CMAKE_CURRENT_SOURCE_DIR}/src/sendinline.cpp) 2 | 3 | target_include_directories(sendinline PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include 4 | "$") 5 | 6 | set_target_properties(sendinline PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -------------------------------------------------------------------------------- /contracts/test_contracts/sendinline/src/sendinline.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /// `eosio.code` is a virtual permission (there is no private or public 8 | /// key associated with it). Therefore, this test tests how `eosio.msig` 9 | /// contract reacts to a smart contract submitting a proposal and 10 | /// approving/unnapproving itself. 11 | class [[eosio::contract]] 12 | sendinline : public eosio::contract { 13 | public: 14 | using contract::contract; 15 | 16 | [[eosio::action]] 17 | void send( eosio::name contract, eosio::name action_name, std::vector auths, std::vector payload) { 18 | eosio::action act; 19 | act.account = contract; 20 | act.name = action_name; 21 | act.authorization = auths; 22 | act.data = std::move(payload); 23 | act.send(); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /docs/01_key-concepts/01_system.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: System contracts, system accounts, privileged accounts 3 | --- 4 | 5 | At the genesis of the Vaulta blockchain, there was only one account present, `eosio` account, which was and still is the main `system account`. During the Vaulta blockchain bootstrap process other `system account`s, were created by `eosio` account, which control specific actions of the `system contract`s. You can see them listed in the [About System Contract](../index.md#system-contracts-defined-in-system-contracts) section. 6 | 7 | __Note__ the terms `system contract` and `system account`. `Privileged accounts` are accounts which can execute a transaction while skipping the standard authorization check. To ensure that this is not a security hole, the permission authority over these accounts is granted to `eosio.prods` system account. 8 | 9 | As you just learned the relation between a `system account` and a `system contract`, it is also important to remember that not all system accounts contain a system contract, but each system account has important roles in the blockchain functionality, as follows: 10 | 11 | |Account|Privileged|Has contract|Description| 12 | |---|---|---|---| 13 | |eosio|Yes|It contains the `eosio.system` contract|The main system account on the Vaulta blockchain.| 14 | |eosio.msig|Yes|It contains the `eosio.msig` contract|Allows the signing of a multi-sig transaction proposal for later execution if all required parties sign the proposal before the expiration time.| 15 | |eosio.wrap|Yes|It contains the `eosio.wrap` contract.|Simplifies block producer superuser actions by making them more readable and easier to audit.| 16 | |eosio.token|No|It contains the `eosio.token` contract.|Defines the structures and actions allowing users to create, issue, and manage tokens on the Vaulta blockchain.| 17 | |eosio.names|No|No|The account which is holding funds from namespace auctions.| 18 | |eosio.bpay|No|No|The account that pays the block producers for producing blocks. It assigns 0.25% of the inflation based on the amount of blocks a block producer created in the last 24 hours.| 19 | |eosio.prods|No|No|The account representing the union of all current active block producers permissions.| 20 | |eosio.ram|No|No|The account that keeps track of the Vaulta balances based on users actions of buying or selling RAM.| 21 | |eosio.ramfee|No|No|The account that keeps track of the fees collected from users RAM trading actions: 0.5% from the value of each trade goes into this account.| 22 | |eosio.saving|No|No|The account which holds the 4% of network inflation.| 23 | |eosio.stake|No|No|The account that keeps track of all Vaulta tokens which have been staked for voting.| 24 | |eosio.vpay|No|No|The account that pays the block producers accordingly with the votes won. It assigns 0.75% of inflation based on the amount of votes a block producer won in the last 24 hours.| 25 | |eosio.rex|No|No|The account that keeps track of fees and balances resulted from REX related actions execution.| 26 | -------------------------------------------------------------------------------- /docs/01_key-concepts/02_system_resources.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: System Resources 3 | --- 4 | 5 | The Vaulta blockchain works with three system resources: CPU, NET and RAM. The Vaulta accounts need sufficient system resources to interact with the smart contracts deployed on the blockchain. 6 | 7 | * [RAM Resource](./05_ram.md) 8 | * [CPU Resource](./03_cpu.md) 9 | * [NET Resource](./04_net.md) 10 | 11 | To allocate RAM resources to an account you have to [purchase RAM](./05_ram.md#how-to-purchase-ram). 12 | To allocate CPU and NET resources to an account you have to [power up the account](./07_powerup_model.md#power-up-your-account). 13 | 14 | ## Resource Cost Estimation 15 | 16 | As a developer if you want to estimate how much CPU and NET a transaction requires for execution, you can employ one of the following methods: 17 | 18 | * Use the `--dry-run` option for the `cleos push transaction` command. 19 | * Use any tool that can pack a transaction and send it to the blockchain and specify the `--dry-run` option. 20 | * Use the chain API endpoint [`compute_transaction`](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp#L557). 21 | 22 | In all cases, when the transaction is processed, the blockchain node simulates the execution of the transaction and, as a consequence, the state of the blockchain is changed speculatively, which allows for the CPU and NET measurements to be done. However, the transaction is not sent to the blockchain and the caller receives the estimated CPU and NET costs in return. 23 | -------------------------------------------------------------------------------- /docs/01_key-concepts/03_cpu.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CPU as system resource 3 | --- 4 | 5 | As NET and RAM, the CPU resource is a very important system resource in the Vaulta blockchain. The CPU system resource provides processing power to blockchain accounts. When the blockchain executes a transaction, it consumes CPU and NET. For transactions to complete, sufficient CPU must be allocated to the payer account. The amount of CPU an account has is measured in microseconds and it is referred to as `cpu bandwidth` on the `cleos get account` command output. 6 | 7 | ## How Is CPU Calculated 8 | 9 | Transactions executed by the blockchain contain one or more actions. Each transaction must consume an amount of CPU within the limits predefined by the minimum and maximum transaction CPU usage values. For Vaulta blockchain these limits are set in the blockchain's configuration. You can find out these limits by running the following command and consult the `min_transaction_cpu_usage` and the `max_transaction_cpu_usage` which are expressed in microseconds: 10 | 11 | ```shell 12 | cleos get consensus_parameters 13 | ``` 14 | 15 | For accounts that execute transactions, the blockchain calculates and updates the remaining resources with each block before each transaction is executed. When a transaction is prepared for execution, the blockchain determines whether the payer account has enough CPU to cover the transaction execution. To calculate the necessary CPU, the node that actively builds the current block measures the time to execute the transaction. If the account has enough CPU, the transaction is executed; otherwise it is rejected. For technical details please refer to the following links: 16 | 17 | * [The CPU configuration variables](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L69-L73) 18 | * [The transaction initialization](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/controller.cpp#L3012) 19 | * [The transaction CPU billing](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/controller.cpp#L3030) 20 | * [The check of CPU usage for a transaction](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/transaction_context.cpp#L457) 21 | 22 | ## Subjective CPU Billing 23 | 24 | Subjective billing is an optional feature of the Vaulta blockchain. It allows nodes to bill account resources locally in their own node without sharing the billing with the rest of the network. Since its introduction, subjective billing benefited the nodes that adopted it because it reduced the node CPU usage by almost 90%. But it can result in failed transactions or lost transactions. Subjective billing can trigger transaction failure when a smart contract code uses a "check" function, like `assert()` or `check()` command to verify data. When this situation occurs, assert or check earlier in the system contract execution to reduce the applied billing. If the lack of an error message does not affect the user experience, a system contract may benefit by replacing some asserts and checks with a return statement. This replacement ensures their transactions succeed and are billed objectively on-chain. 25 | 26 | Find more details about subjective billing in the [Introduction to subjective billing and lost transactions](https://eosnetwork.com/blog/api-plus-an-introduction-to-subjective-billing-and-lost-transactions/) article. 27 | 28 | ## How To Rent CPU 29 | 30 | For details on how to rent CPU resources refer to the [Account Power Up](./07_powerup_model.md#power-up-your-account) section. 31 | -------------------------------------------------------------------------------- /docs/01_key-concepts/04_net.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: NET as system resource 3 | --- 4 | 5 | As CPU and RAM, the NET resource is an important system resource in the Vaulta blockchain. When the blockchain executes a transaction, it consumes CPU and NET. Sufficient NET must be allocated to the payer account for transactions to complete. NET is referred to as `net bandwidth` on the `cleos get account` command output. 6 | 7 | ## How Is NET Calculated 8 | 9 | Each transaction must consume an amount of NET which can not exceed the predefined maximum transaction NET usage value. For Vaulta blockchain this limit is set in the blockchain's configuration. You can find out this limit by running the following command and consult the `max_transaction_net_usage` which is expressed in bytes. 10 | 11 | ```shell 12 | cleos get consensus_parameters 13 | ``` 14 | 15 | For the accounts that execute transactions, the blockchain calculates and updates the remaining resources for each block before each transaction is executed. When a transaction is prepared for execution, the blockchain determines whether the payer account has enough NET to cover the transaction execution. The necessary NET is calculated based on the transaction size, which is the size of the packed transaction as it is stored in the blockchain. If the account has enough NET resources, the transaction can be executed; otherwise it is rejected. For technical details please refer to the following sources: 16 | 17 | * [The NET configuration variables](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L60-L67) 18 | * [The transaction initialization](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/controller.cpp#L3012) 19 | * [The transaction NET billing](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/controller.cpp#L3030) 20 | * [The check of NET usage for a transaction](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/transaction_context.cpp#L416) 21 | 22 | ## How To Rent NET 23 | 24 | For details on how to rent NET resources refer to the [Account Power Up](./07_powerup_model.md#power-up-your-account) section. 25 | -------------------------------------------------------------------------------- /docs/01_key-concepts/05_ram.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: RAM as system resource 3 | --- 4 | 5 | The RAM resource is the memory, the storage space, where the blockchain stores data. If your contract needs to store data on the blockchain, it can store it in the blockchain's RAM as a `multi-index table` or a `singleton`. 6 | 7 | ## RAM High Performance 8 | 9 | Data stored on the Vaulta blockchain uses RAM as its storage medium. Therefore, access to the blockchain data is highly performant and fast. Its performance benchmarks can reach levels rarely achieved by other blockchains. This ability elevates the Vaulta blockchain to be a contender for the fastest blockchain worldwide. 10 | 11 | ## RAM Importance 12 | 13 | RAM is an important system resource because of the following reasons: 14 | 15 | * Ram is a limited resource. The public Vaulta blockchain started with 64GB of total RAM. After a brief period the block producers decided to increase the memory with 1KB per block. In this way the supply of RAM constantly increases, yet its price accelerates at a slower pace. 16 | 17 | * The execution of many actions by the blockchain uses RAM. For example, when you create a new account, the new account information is stored in the blockchain's RAM. Also, when an account accepts a token which it did not hold before, a new record has to be created, that holds the balance of the newly accepted token. The blockchain memory has to be purchased either by the account that transfers the tokens or by the account that accepts the new token type. 18 | 19 | * If a smart contract consumes all of its allocated RAM, it cannot store any additional information. To continue to save data in the blockchain database, one or both of the following conditions must be met: 20 | 21 | * A portion of the occupied RAM is freed by the smart contract. 22 | * More RAM is allocated to the smart contract account through the RAM purchase process. 23 | 24 | ## How To Purchase RAM 25 | 26 | The RAM resource must be bought with the `EOS` system token. The price of RAM is calculated according to the unique Bancor liquidity algorithm that is implemented in the system contract. 27 | 28 | The quickest way to calculate the price of RAM: 29 | 30 | 1. Run the following command: (**Note:** Make sure you run it against the mainnet or the testnet of your choice.) 31 | 32 | ```shell 33 | cleos get table eosio eosio rammarket 34 | ``` 35 | 36 | 2. Observe the output which should look like the sample below: 37 | 38 | ```text 39 | { 40 | "supply": "10000000000.0000 RAMCORE", 41 | "base": { 42 | "balance": "35044821247 RAM", 43 | "weight": "0.50000000000000000" 44 | }, 45 | "quote": { 46 | "balance": "3158350.8754 EOS", 47 | "weight": "0.50000000000000000" 48 | } 49 | } 50 | ``` 51 | 52 | 3. Make note of the `base balance`, in this case it is 35044821247. 53 | 4. Make note of the `quote balance`, in this case it is 3158350.8754. 54 | 5. Calculate the price of 1Kib of RAM as `quote balance` * 1024 / `base balance` = 0.0922 EOS. 55 | 56 | ### Buy RAM With Command Line Interface 57 | 58 | You can buy RAM through the command line interface tool. You can buy either an explicit amount of RAM expressed in bytes or an amount of RAM worth an explicit amount of Vaulta. 59 | 60 | ### Buy RAM In EOS 61 | 62 | For example, the command below buys for account `bob` 0.1 EOS worth of RAM at the current market RAM price. The cost for the RAM and the execution of this transaction is covered by the `alice` account and the transaction is authorized by the `active` key of the `alice` account. 63 | 64 | ```shell 65 | cleos system buyram alice bob "0.1 EOS" -p alice@active 66 | ``` 67 | 68 | ### Buy RAM In Bytes 69 | 70 | For example, the command below buys for account `bob` 1000 RAM bytes at the current market RAM price. The cost for the RAM and the execution of this transaction is covered by the `alice` account and the transaction is authorized by the `active` key of the `alice` account. 71 | 72 | ```shell 73 | cleos system buyrambytes alice bob "1000" -p alice@active 74 | ``` 75 | 76 | ## How Is RAM Calculated 77 | 78 | The necessary RAM needed for a smart contract to store its data is calculated from the used blockchain state. 79 | 80 | As a developer, to understand the amount of RAM your smart contract needs, pay attention to the data structure underlying the multi-index tables your smart contract instantiates and uses. The data structure underlying one multi-index table defines a row in the table. Each data member of the data structure corresponds with a row cell of the table. 81 | To approximate the amount of RAM one multi-index row needs to store on the blockchain, you have to add the size of the type of each data member and the memory overheads for each of the defined indexes, if any. Find below the overheads defined by the Vaulta code for multi-index tables, indexes, and data types: 82 | 83 | * [Multi-index RAM bytes overhead](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/contract_table_objects.hpp#L242-L285) 84 | * [Overhead per row per index RAM bytes](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L114) 85 | * [Fixed overhead shared vector RAM bytes](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L113) 86 | * [Overhead per account RAM bytes](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L115) 87 | * [Setcode RAM bytes multiplier](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/include/eosio/chain/config.hpp#L116) 88 | * [RAM usage update function](https://github.com/AntelopeIO/spring/blob/7254bab917a17bcc0d82d23d03f4173176150239/libraries/chain/apply_context.cpp#L734) 89 | -------------------------------------------------------------------------------- /docs/01_key-concepts/06_vote.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Voting on Vaulta blockchain 3 | --- 4 | 5 | The Vaulta blockchain is kept alive by nodes which are interconnected between each other, communicating with each other via peer to peer protocols. Some of these nodes are elected, via a voting process, by the token holders to be producer nodes. They produce blocks, validate them and reach consensus on what transactions are allowed in each block, their order, and what blocks are finalized and stored forever in the blockchain state. This way the governance, the mechanism by which collective decisions are made, of the blockchain is achieved through the 21 active block producers which are appointed by token holders' votes. It is the 21 active block producers which continuously advancing the blockchain by creating blocks, and securing them by validating them, and reaching consensus. Consensus is reached when 2/3+1 active block producers agree on validity of a block, that is all transactions contained in it and their order. The 21 producers is the default value however it can be configured to be higher or smaller to meet each business case requirements. 6 | 7 | The 21 block producers are elected through the voting process. Each EOS token holder that wants to vote for one or up to 30 block producers must stake their tokens. The more tokens are stake the more voting power. The voting power of one account is proportional with the amount of tokens staked by that account versus the total amount of tokens staked by whole accounts that stake their tokens. 8 | -------------------------------------------------------------------------------- /docs/01_key-concepts/07_powerup_model.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How To Use The PowerUp Model 3 | --- 4 | 5 | ## Power Up Your Account 6 | 7 | To power up an account is a technique to rent CPU and NET resources from the PowerUp resource model. A smart contract implements this model on the blockchain and allocates these resources to the account of your choice. The action to power up an account is `powerup`. It takes as parameters: 8 | 9 | * The `payer` of the fee, must be a valid Vaulta account. 10 | * The `receiver` of the resources, must be a valid Vaulta account. 11 | * The `days` which must always match `state.powerup_days` specified in the [PowerUp configuration settings](https://github.com/VaultaFoundation/system-contracts/blob/7cec470b17bd53b8c78465d4cbd889dbaf1baffb/contracts/eosio.system/include/eosio.system/eosio.system.hpp#L588). 12 | * The `net_frac`, and the `cpu_frac` are the percentage of the resources that you need. The easiest way to calculate the percentage is to multiple 10^15 (100%) by the desired percentage. For example: 10^15 * 0.01 = 10^13. 13 | * The `max_payment`, must be expressed in EOS and is the maximum amount the `payer` is willing to pay. 14 | 15 | ```sh 16 | cleos push action eosio powerup '[user, user, 1, 10000000000000, 10000000000000, "1000.0000 EOS"]' -p user 17 | ``` 18 | 19 | To view the received NET and CPU weight as well as the amount of the fee, check the `eosio.reserv::powupresult` returned by the action, which should look similar to the one below: 20 | 21 | ```console 22 | executed transaction: 82b7124601612b371b812e3bf65cf63bb44616802d3cd33a2c0422b58399f54f 144 bytes 521 us 23 | # eosio <= eosio::powerup {"payer":"user","receiver":"user","days":1,"net_frac":"10000000000000","cpu_frac":"10000000000000","... 24 | # eosio.token <= eosio.token::transfer {"from":"user","to":"eosio.rex","quantity":"999.9901 EOS","memo":"transfer from user to eosio.rex"} 25 | # eosio.reserv <= eosio.reserv::powupresult {"fee":"999.9901 EOS","powup_net_weight":"16354","powup_cpu_weight":"65416"} 26 | # user <= eosio.token::transfer {"from":"user","to":"eosio.rex","quantity":"999.9901 EOS","memo":"transfer from user to eosio.rex"} 27 | # eosio.rex <= eosio.token::transfer {"from":"user","to":"eosio.rex","quantity":"999.9901 EOS","memo":"transfer from user to eosio.rex"} 28 | ``` 29 | 30 | The PowerUp resource model on the Vaulta blockchain is initialized with `"powerup_days": 1,`. This setting permits the maximum period to rent CPU and NET for 24 hours. If you do not use the resources within the 24 hour interval, the rented CPU and NET expires. 31 | 32 | ### Process Expired Orders 33 | 34 | The resources in loans that expire are not automatically reclaimed by the system. The expired loans remain in a queue that must be processed. 35 | 36 | Any calls to the `powerup` action does process also this queue (limited to two expired loans at a time). Therefore, the expired loans are automatically processed in a timely manner. Sometimes, it may be necessary to manually process expired loans in the queue to release resources back to the system, which reduces prices. Therefore, any account may process up to an arbitrary number of expired loans if it calls the `powerupexec` action. 37 | 38 | To view the orders table `powup.order` execute the following command: 39 | 40 | ```sh 41 | cleos get table eosio 0 powup.order 42 | ``` 43 | 44 | ```json 45 | { 46 | "rows": [{ 47 | "version": 0, 48 | "id": 0, 49 | "owner": "user", 50 | "net_weight": 16354, 51 | "cpu_weight": 65416, 52 | "expires": "2020-11-18T13:04:33" 53 | } 54 | ], 55 | "more": false, 56 | "next_key": "" 57 | } 58 | ``` 59 | 60 | Example `powerupexec` call: 61 | 62 | ```sh 63 | cleos push action eosio powerupexec '[user, 2]' -p user 64 | ``` 65 | 66 | ```console 67 | executed transaction: 93ab4ac900a7902e4e59e5e925e8b54622715328965150db10774aa09855dc98 104 bytes 363 us 68 | # eosio <= eosio::powerupexec {"user":"user","max":2} 69 | warning: transaction executed locally, but may not be confirmed by the network yet ] 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/03_build-and-deploy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to build the Vaulta system contracts 3 | --- 4 | 5 | For building instructions, refer to the [Building](https://github.com/VaultaFoundation/system-contracts#building) section. 6 | -------------------------------------------------------------------------------- /docs/04_guides/02_how-to-buy-ram.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to buy RAM 3 | link_text: How to buy RAM 4 | --- 5 | 6 | ## Goal 7 | 8 | Setup an account that require multiple signatures for signing a transaction 9 | 10 | ## Before you begin 11 | 12 | * You have an account 13 | 14 | * Ensure the reference system contracts from `system-contracts` repository is deployed and used to manage system resources 15 | 16 | * You have sufficient token allocated to your account 17 | 18 | * Install the currently supported version of cleos 19 | 20 | * Unlock your wallet 21 | 22 | ## Steps 23 | 24 | Buys RAM in value of 10 EOS tokens for account `alice`: 25 | 26 | ```shell 27 | cleos system buyram alice alice "10 EOS" -p alice@active 28 | ``` -------------------------------------------------------------------------------- /docs/04_guides/03_how-to-stake.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to stake 3 | link_text: How to stake 4 | --- 5 | 6 | ## Goal 7 | 8 | Stake resources for your account to participate in the on-chain voting and governance. 9 | 10 | ## Before you begin 11 | 12 | * Install the currently supported version of cleos 13 | 14 | * Ensure the reference system contracts from `system-contracts` repository is deployed and used to manage system resources 15 | 16 | * Understand the following: 17 | * What is an account 18 | * What is network bandwidth 19 | * What is CPU bandwidth 20 | 21 | ## Steps 22 | 23 | Stake 10 EOS network bandwidth for `alice` 24 | 25 | ```shell 26 | cleos system delegatebw alice alice "0 EOS" "10 EOS" 27 | ``` 28 | 29 | Stake 10 EOS CPU bandwidth for `alice`: 30 | 31 | ```shell 32 | cleos system delegatebw alice alice "10 EOS" "0 EOS" 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/04_guides/04_how-to-vote.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to vote 3 | link_text: How to vote 4 | --- 5 | 6 | ## Goal 7 | 8 | Vote for a block producer 9 | 10 | ## Before you begin 11 | 12 | * Install the current supported version of cleos 13 | 14 | * Ensure the reference system contracts from `system-contracts` repository is deployed and used to manage system resources 15 | 16 | * Understand the following: 17 | * What is a block producer 18 | * How does voting works 19 | 20 | * Unlock your wallet 21 | 22 | ## Steps 23 | 24 | Assume you are going to vote for blockproducer1 and blockproducer2 from an account called `eosiotestts2`, execute the following: 25 | 26 | ```bash 27 | cleos system voteproducer prods eosiotestts2 blockproducer1 blockproducer2 28 | ``` 29 | 30 | You should see something like below: 31 | 32 | ```console 33 | executed transaction: 2d8b58f7387aef52a1746d7a22d304bbbe0304481d7751fc4a50b619df62676d 128 bytes 374 us 34 | # eosio <= eosio::voteproducer {"voter":"eosiotestts2","proxy":"","producers":["blockproducer1","blockproducer2"]} 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/04_guides/05_how-to-create-issue-and-transfer-a-token.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to create, issue and transfer a token 3 | link_text: How to create, issue and transfer a token 4 | --- 5 | 6 | ## Step 1: Obtain Contract Source 7 | 8 | Navigate to your contracts directory. 9 | 10 | ```sh 11 | cd CONTRACTS_DIR 12 | ``` 13 | 14 | Pull the source 15 | 16 | ```sh 17 | git clone https://github.com/VaultaFoundation/system-contracts --branch release/3.1 --single-branch 18 | ``` 19 | 20 | ```sh 21 | cd system-contracts/contracts/eosio.token 22 | ``` 23 | 24 | ## Step 2: Create Account for Contract 25 | 26 | [[info]] 27 | | You may have to unlock your wallet first! 28 | 29 | ```shell 30 | cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV 31 | ``` 32 | 33 | ## Step 3: Compile the Contract 34 | 35 | ```shell 36 | eosio-cpp -I include -o eosio.token.wasm src/eosio.token.cpp --abigen 37 | ``` 38 | 39 | ## Step 4: Deploy the Token Contract 40 | 41 | ```shell 42 | 43 | cleos set contract eosio.token CONTRACTS_DIR/system-contracts/contracts/eosio.token --abi eosio.token.abi -p eosio.token@active 44 | ``` 45 | 46 | Result should look similar to the one below: 47 | 48 | ```console 49 | Reading WASM from ... 50 | Publishing contract... 51 | executed transaction: 69c68b1bd5d61a0cc146b11e89e11f02527f24e4b240731c4003ad1dc0c87c2c 9696 bytes 6290 us 52 | # eosio <= eosio::setcode {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d0100000001aa011c60037f7e7f0060047f... 53 | # eosio <= eosio::setabi {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e30000605636c6f73650002056f776e6572046e61... 54 | warning: transaction executed locally, but may not be confirmed by the network yet ] 55 | ``` 56 | 57 | ## Step 5: Create the Token 58 | 59 | ```shell 60 | cleos push action eosio.token create '[ "eosio", "1000000000.0000 NEWT"]' -p eosio.token@active 61 | ``` 62 | 63 | Result should look similar to the one below: 64 | 65 | ```console 66 | executed transaction: 0e49a421f6e75f4c5e09dd738a02d3f51bd18a0cf31894f68d335cd70d9c0e12 120 bytes 1000 cycles 67 | # eosio.token <= eosio.token::create {"issuer":"eosio","maximum_supply":"1000000000.0000 NEWT"} 68 | ``` 69 | 70 | An alternate approach uses named arguments: 71 | 72 | ```shell 73 | cleos push action eosio.token create '{"issuer":"eosio", "maximum_supply":"1000000000.0000 NEWT"}' -p eosio.token@active 74 | ``` 75 | 76 | Result should look similar to the one below: 77 | 78 | ```console 79 | executed transaction: 0e49a421f6e75f4c5e09dd738a02d3f51bd18a0cf31894f68d335cd70d9c0e12 120 bytes 1000 cycles 80 | # eosio.token <= eosio.token::create {"issuer":"eosio","maximum_supply":"1000000000.0000 NEWT"} 81 | ``` 82 | 83 | This command created a new token `NEWT` with a precision of 4 decimals and a maximum supply of 1000000000.0000 NEWT. To create this token requires the permission of the `eosio.token` contract. For this reason, `-p eosio.token@active` was passed to authorize the request. 84 | 85 | ## Step 6: Issue Tokens 86 | 87 | The issuer can issue new tokens to the issuer account in our case `eosio`. 88 | 89 | ```sh 90 | cleos push action eosio.token issue '[ "eosio", "100.0000 NEWT", "memo" ]' -p eosio@active 91 | ``` 92 | 93 | Result should look similar to the one below: 94 | 95 | ```console 96 | executed transaction: a26b29d66044ad95edf0fc04bad3073e99718bc26d27f3c006589adedb717936 128 bytes 337 us 97 | # eosio.token <= eosio.token::issue {"to":"eosio","quantity":"100.0000 NEWT","memo":"memo"} 98 | warning: transaction executed locally, but may not be confirmed by the network yet ] 99 | ``` 100 | 101 | ## Step 7: Transfer Tokens 102 | 103 | Now that account `eosio` has been issued tokens, transfer some of them to account `bob`. 104 | 105 | ```shell 106 | cleos push action eosio.token transfer '[ "eosio", "bob", "25.0000 NEWT", "m" ]' -p eosio@active 107 | ``` 108 | 109 | Result should look similar to the one below: 110 | 111 | ```console 112 | executed transaction: 60d334850151cb95c35fe31ce2e8b536b51441c5fd4c3f2fea98edcc6d69f39d 128 bytes 497 us 113 | # eosio.token <= eosio.token::transfer {"from":"eosio","to":"bob","quantity":"25.0000 NEWT","memo":"m"} 114 | # eosio <= eosio.token::transfer {"from":"eosio","to":"bob","quantity":"25.0000 NEWT","memo":"m"} 115 | # bob <= eosio.token::transfer {"from":"eosio","to":"bob","quantity":"25.0000 NEWT","memo":"m"} 116 | warning: transaction executed locally, but may not be confirmed by the network yet ] 117 | ``` 118 | 119 | Now check if "bob" got the tokens using [cleos get currency balance](https://github.com/AntelopeIO/spring/blob/v1.0.0-rc2/docs/02_cleos/03_command-reference/get/currency-balance.md) 120 | 121 | ```shell 122 | cleos get currency balance eosio.token bob NEWT 123 | ``` 124 | 125 | Result: 126 | 127 | ```console 128 | 25.00 NEWT 129 | ``` 130 | 131 | Check "eosio's" balance, notice that tokens were deducted from the account 132 | 133 | ```shell 134 | cleos get currency balance eosio.token eosio NEWT 135 | ``` 136 | 137 | Result: 138 | 139 | ```console 140 | 75.00 NEWT 141 | ``` 142 | -------------------------------------------------------------------------------- /docs/04_guides/06_how-to-sign-a-multisig-transaction-with-eosio.msig.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to sign a multisig transaction with eosio.msig 3 | link_text: How to sign a multisig transaction with eosio.msig 4 | --- 5 | 6 | ### eosio.msig 7 | 8 | ### Prerequisites: 9 | - eosio.token contract installed to eosio.token account, eosio.msig contract installed on eosio.msig account which is a priviliged account. 10 | - account 'treasury' is the issuer of EOS token. 11 | - account 'tester' exists. 12 | - keys to accounts 'treasury' and 'tester' imported into local wallet, the wallet is unlocked. 13 | 14 | ### One user creates a proposal: 15 | ```sh 16 | cleos multisig propose test '[{"actor": "treasury", "permission": "active"}]' '[{"actor": "treasury", "permission": "active"}]' eosio.token issue '{"to": "tester", "quantity": "1000.0000 EOS", "memo": ""}' -p tester 17 | ``` 18 | ```console 19 | executed transaction: e26f3a3a7cba524a7b15a0b6c77c7daa73d3ba9bf84e83f9c2cdf27fcb183d61 336 bytes 107520 cycles 20 | # eosio.msig <= eosio.msig::propose {"proposer":"tester","proposal_name":"test","requested":[{"actor":"treasury","permission":"active"}]... 21 | ``` 22 | 23 | ### Another user reviews the transaction: 24 | ```sh 25 | cleos multisig review tester test 26 | ``` 27 | ```json 28 | { 29 | "proposal_name": "test", 30 | "requested_approvals": [{ 31 | "actor": "treasury", 32 | "permission": "active" 33 | } 34 | ], 35 | "provided_approvals": [], 36 | "packed_transaction": "00aee75a0000000000000000000000000100a6823403ea30550000000000a5317601000000fe6a6cd4cd00000000a8ed323219000000005c95b1ca809698000000000004454f530000000000", 37 | "transaction": { 38 | "expiration": "2018-05-01T00:00:00", 39 | "region": 0, 40 | "ref_block_num": 0, 41 | "ref_block_prefix": 0, 42 | "max_net_usage_words": 0, 43 | "max_kcpu_usage": 0, 44 | "delay_sec": 0, 45 | "context_free_actions": [], 46 | "actions": [{ 47 | "account": "eosio.token", 48 | "name": "issue", 49 | "authorization": [{ 50 | "actor": "treasury", 51 | "permission": "active" 52 | } 53 | ], 54 | "data": { 55 | "to": "tester", 56 | "quantity": "1000.0000 EOS", 57 | "memo": "" 58 | }, 59 | "hex_data": "000000005c95b1ca809698000000000004454f530000000000" 60 | } 61 | ] 62 | } 63 | } 64 | ``` 65 | 66 | ### And then approves it: 67 | ```sh 68 | cleos multisig approve tester test '{"actor": "treasury", "permission": "active"}' -p treasury 69 | ``` 70 | ```console 71 | executed transaction: 475970a4b0016368d0503d1ce01577376f91f5a5ba63dd4353683bd95101b88d 256 bytes 108544 cycles 72 | # eosio.msig <= eosio.msig::approve {"proposer":"tester","proposal_name":"test","level":{"actor":"treasury","permission":"active"}} 73 | ``` 74 | 75 | ### First user initiates execution: 76 | ```sh 77 | cleos multisig exec tester test -p tester 78 | ``` 79 | ```console 80 | executed transaction: 64e5eaceb77362694055f572ae35876111e87b637a55250de315b1b55e56d6c2 248 bytes 109568 cycles 81 | # eosio.msig <= eosio.msig::exec {"proposer":"tester","proposal_name":"test","executer":"tester"} 82 | ``` 83 | 84 | 85 | ## Cleos usage example for transferring tokens. 86 | 87 | ### Prerequisites: 88 | - eosio.token contract installed to eosio.token account, eosio.msig contract installed on eosio.msig account which is a priviliged account. 89 | - account 'treasury' has at least 1.1000 EOS token balance. 90 | - account 'tester' exists. 91 | - keys to accounts 'treasury' and 'tester' imported into local wallet, the wallet is unlocked. 92 | 93 | ### One user creates a proposal: 94 | ```sh 95 | cleos multisig propose test '[{"actor": "treasury", "permission": "active"}]' '[{"actor": "treasury", "permission": "active"}]' eosio.token transfer '{"from": "treasury", "to": "tester", "quantity": "1.0000 EOS", "memo": ""}' -p tester 96 | ``` 97 | ```console 98 | executed transaction: e26f3a3a7cba524a7b15a0b6c77c7daa73d3ba9bf84e83f9c2cdf27fcb183d61 336 bytes 107520 cycles 99 | # eosio.msig <= eosio.msig::propose {"proposer":"tester","proposal_name":"test","requested":[{"actor":"treasury","permission":"active"}]... 100 | ``` 101 | 102 | ### Another user reviews the transaction: 103 | ```sh 104 | cleos multisig review tester test 105 | ``` 106 | ```json 107 | { 108 | "proposal_name": "test", 109 | "requested_approvals": [{ 110 | "actor": "treasury", 111 | "permission": "active" 112 | } 113 | ], 114 | "provided_approvals": [], 115 | "packed_transaction": "00aee75a0000000000000000000000000100a6823403ea30550000000000a5317601000000fe6a6cd4cd00000000a8ed323219000000005c95b1ca809698000000000004454f530000000000", 116 | "transaction": { 117 | "expiration": "2018-05-01T00:00:00", 118 | "region": 0, 119 | "ref_block_num": 0, 120 | "ref_block_prefix": 0, 121 | "max_net_usage_words": 0, 122 | "max_kcpu_usage": 0, 123 | "delay_sec": 0, 124 | "context_free_actions": [], 125 | "actions": [{ 126 | "account": "eosio.token", 127 | "name": "transfer", 128 | "authorization": [{ 129 | "actor": "treasury", 130 | "permission": "active" 131 | } 132 | ], 133 | "data": { 134 | "from": "treasury", 135 | "to": "tester", 136 | "quantity": "1.0000 EOS", 137 | "memo": "" 138 | }, 139 | "hex_data": "000000005c95b1ca809698000000000004454f530000000000" 140 | } 141 | ] 142 | } 143 | } 144 | ``` 145 | 146 | ### And then approves it: 147 | ```sh 148 | cleos multisig approve tester test '{"actor": "treasury", "permission": "active"}' -p treasury 149 | ``` 150 | ```console 151 | executed transaction: 475970a4b0016368d0503d1ce01577376f91f5a5ba63dd4353683bd95101b88d 256 bytes 108544 cycles 152 | # eosio.msig <= eosio.msig::approve {"proposer":"tester","proposal_name":"test","level":{"actor":"treasury","permission":"active"}} 153 | ``` 154 | 155 | ### First user check account balance before executing the proposed transaction 156 | ```sh 157 | cleos get table eosio.token tester accounts | jq '.rows[]' 158 | ``` 159 | ```console 160 | ... 161 | EOS balances: 162 | liquid: 1.0487 EOS 163 | staked: 2.0000 EOS 164 | unstaking: 0.0000 EOS 165 | total: 4.0487 EOS 166 | ``` 167 | 168 | ### First user initiates execution of proposed transaction: 169 | ```sh 170 | cleos multisig exec tester test -p tester 171 | ``` 172 | ```console 173 | executed transaction: 64e5eaceb77362694055f572ae35876111e87b637a55250de315b1b55e56d6c2 248 bytes 109568 cycles 174 | # eosio.msig <= eosio.msig::exec {"proposer":"tester","proposal_name":"test","executer":"tester"} 175 | ``` 176 | 177 | ### First user can check account balance, it should be increased by 1.0000 EOS 178 | ```sh 179 | cleos get table eosio.token tester accounts | jq '.rows[]' 180 | ``` 181 | ```console 182 | ... 183 | EOS balances: 184 | liquid: 2.0487 EOS 185 | staked: 2.0000 EOS 186 | unstaking: 0.0000 EOS 187 | total: 4.0487 EOS 188 | ``` 189 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About System Contracts 3 | --- 4 | 5 | The Vaulta blockchain is unique in that the features and characteristics of the blockchain built on it are flexible, that is, they can be changed, or modified completely to suit the Vaulta community needs. Core blockchain features such as consensus, fee schedules, account creation and modification, token economics, block producer registration, voting, multi-sig, are implemented inside smart contracts which are deployed on the Vaulta blockchain. 6 | 7 | ## System contracts defined in system-contracts 8 | 9 | The `system-contracts` repository contains the system contracts encapsulating the base functionality for the Vaulta blockchain. 10 | 11 | 1. [eosio.bios](action-reference/eosio.bios) 12 | 2. [eosio.system](action-reference/eosio.system) 13 | 3. [eosio.msig](action-reference/eosio.msig) 14 | 4. [eosio.token](action-reference/eosio.token) 15 | 5. [eosio.wrap](action-reference/eosio.wrap) 16 | 17 | ## Key Concepts Implemented by eosio.system 18 | 19 | 1. [System](01_key-concepts/01_system.md) 20 | 2. [System Resources](01_key-concepts/02_system_resources.md) 21 | 3. [CPU](01_key-concepts/03_cpu.md) 22 | 4. [NET](01_key-concepts/04_net.md) 23 | 5. [RAM](01_key-concepts/05_ram.md) 24 | 6. [Vote](01_key-concepts/06_vote.md) 25 | 26 | ## Build and deploy 27 | 28 | To build and deploy the system contract follow the instruction from [Build and deploy](03_build-and-deploy.md) section. -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | set(EOSIO_VERSION_MIN "1.0") 4 | set(EOSIO_VERSION_SOFT_MAX "1.0") 5 | # set(EOSIO_VERSION_HARD_MAX "") 6 | 7 | find_package(spring) 8 | 9 | # Check the version of Spring 10 | if(SYSTEM_ENABLE_SPRING_VERSION_CHECK) 11 | set(VERSION_MATCH_ERROR_MSG "") 12 | eosio_check_version(VERSION_OUTPUT "${EOSIO_VERSION}" "${EOSIO_VERSION_MIN}" "${EOSIO_VERSION_SOFT_MAX}" 13 | "${EOSIO_VERSION_HARD_MAX}" VERSION_MATCH_ERROR_MSG) 14 | if(VERSION_OUTPUT STREQUAL "MATCH") 15 | message(STATUS "Using Spring version ${EOSIO_VERSION}") 16 | elseif(VERSION_OUTPUT STREQUAL "WARN") 17 | message( 18 | WARNING 19 | "Using Spring version ${EOSIO_VERSION} even though it exceeds the maximum supported version of ${EOSIO_VERSION_SOFT_MAX}; continuing with configuration, however build may fail.\nIt is recommended to use Spring version ${EOSIO_VERSION_SOFT_MAX}.x" 20 | ) 21 | else() # INVALID OR MISMATCH 22 | message( 23 | FATAL_ERROR 24 | "Found Spring version ${EOSIO_VERSION} but it does not satisfy version requirements: ${VERSION_MATCH_ERROR_MSG}\nPlease use Spring version ${EOSIO_VERSION_SOFT_MAX}.x" 25 | ) 26 | endif(VERSION_OUTPUT STREQUAL "MATCH") 27 | endif() 28 | 29 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/contracts.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/contracts.hpp) 30 | 31 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 32 | # UNIT TESTING ### 33 | include(CTest) # eliminates DartConfiguration.tcl errors at test runtime 34 | enable_testing() 35 | # build unit test executable 36 | file(GLOB UNIT_TESTS "*.cpp" "*.hpp") # find all unit test suites 37 | add_eosio_test_executable(unit_test ${UNIT_TESTS}) # build unit tests as one executable 38 | # mark test suites for execution 39 | foreach(TEST_SUITE ${UNIT_TESTS}) # create an independent target for each test suite 40 | execute_process( 41 | COMMAND 42 | bash -c 43 | "grep -E 'BOOST_AUTO_TEST_SUITE\\s*[(]' ${TEST_SUITE} | grep -vE '//.*BOOST_AUTO_TEST_SUITE\\s*[(]' | cut -d ')' -f 1 | cut -d '(' -f 2" 44 | OUTPUT_VARIABLE SUITE_NAMES 45 | OUTPUT_STRIP_TRAILING_WHITESPACE) # get all the test suite names from each *.cpp file 46 | string(REPLACE "\n" ";" SUITE_NAMES "${SUITE_NAMES}") 47 | foreach(SUITE_NAME IN LISTS SUITE_NAMES) 48 | if(NOT "" STREQUAL "${SUITE_NAME}") # ignore empty lines 49 | execute_process( 50 | COMMAND bash -c "echo ${SUITE_NAME} | sed -e 's/s$//' | sed -e 's/_test$//'" 51 | OUTPUT_VARIABLE TRIMMED_SUITE_NAME 52 | OUTPUT_STRIP_TRAILING_WHITESPACE) # trim "_test" or "_tests" from the end of ${SUITE_NAME} 53 | # to run unit_test with all log from blockchain displayed, put "--verbose" after "--", i.e. "unit_test -- --verbose" 54 | add_test(NAME ${TRIMMED_SUITE_NAME}_unit_test COMMAND unit_test --run_test=${SUITE_NAME} --report_level=detailed 55 | --color_output) 56 | endif() 57 | endforeach(SUITE_NAME) 58 | endforeach(TEST_SUITE) 59 | -------------------------------------------------------------------------------- /tests/contracts.hpp.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace eosio::testing { 5 | 6 | struct contracts { 7 | static std::vector system_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.system/eosio.system.wasm"); } 8 | static std::vector system_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.system/eosio.system.abi"); } 9 | static std::vector token_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.token/eosio.token.wasm"); } 10 | static std::vector fees_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.fees/eosio.fees.wasm"); } 11 | static std::vector token_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.token/eosio.token.abi"); } 12 | static std::vector msig_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.msig/eosio.msig.wasm"); } 13 | static std::vector msig_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.msig/eosio.msig.abi"); } 14 | static std::vector wrap_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.wrap/eosio.wrap.wasm"); } 15 | static std::vector wrap_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.wrap/eosio.wrap.abi"); } 16 | static std::vector bios_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.bios/eosio.bios.wasm"); } 17 | static std::vector bios_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.bios/eosio.bios.abi"); } 18 | static std::vector bpay_wasm() { return read_wasm("${CMAKE_BINARY_DIR}/contracts/eosio.bpay/eosio.bpay.wasm"); } 19 | static std::vector bpay_abi() { return read_abi("${CMAKE_BINARY_DIR}/contracts/eosio.bpay/eosio.bpay.abi"); } 20 | 21 | struct util { 22 | static std::vector reject_all_wasm() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/reject_all.wasm"); } 23 | static std::vector exchange_wasm() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/exchange.wasm"); } 24 | static std::vector system_wasm_v1_8() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.8.3/eosio.system/eosio.system.wasm"); } 25 | static std::vector system_abi_v1_8() { return read_abi("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.8.3/eosio.system/eosio.system.abi"); } 26 | static std::vector system_wasm_old() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.2.1/eosio.system/eosio.system.wasm"); } 27 | static std::vector system_abi_old() { return read_abi("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.2.1/eosio.system/eosio.system.abi"); } 28 | static std::vector msig_wasm_old() { return read_wasm("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.2.1/eosio.msig/eosio.msig.wasm"); } 29 | static std::vector msig_abi_old() { return read_abi("${CMAKE_CURRENT_SOURCE_DIR}/test_contracts/old_versions/v1.2.1/eosio.msig/eosio.msig.abi"); } 30 | }; 31 | }; 32 | 33 | } // namespace eosio::testing 34 | 35 | namespace system_contracts::testing::test_contracts { 36 | 37 | [[maybe_unused]] static std::vector blockinfo_tester_wasm() 38 | { 39 | return eosio::testing::read_wasm( 40 | "${CMAKE_BINARY_DIR}/contracts/test_contracts/blockinfo_tester/blockinfo_tester.wasm"); 41 | } 42 | [[maybe_unused]] static std::vector sendinline_wasm() 43 | { 44 | return eosio::testing::read_wasm( 45 | "${CMAKE_BINARY_DIR}/contracts/test_contracts/sendinline/sendinline.wasm"); 46 | } 47 | [[maybe_unused]] static std::vector sendinline_abi() 48 | { 49 | return eosio::testing::read_abi( 50 | "${CMAKE_BINARY_DIR}/contracts/test_contracts/sendinline/sendinline.abi"); 51 | } 52 | 53 | 54 | } // namespace system_contracts::testing::test_contracts -------------------------------------------------------------------------------- /tests/eosio.bpay_tests.cpp: -------------------------------------------------------------------------------- 1 | #include "eosio.system_tester.hpp" 2 | 3 | using namespace eosio_system; 4 | 5 | BOOST_AUTO_TEST_SUITE(eosio_bpay_tests); 6 | 7 | account_name voter = "alice1111111"_n; 8 | account_name standby = "bp.standby"_n; 9 | account_name inactive = "bp.inactive"_n; 10 | account_name fees = "eosio.fees"_n; 11 | account_name bpay = "eosio.bpay"_n; 12 | 13 | BOOST_FIXTURE_TEST_CASE( bpay_test, eosio_system_tester ) try { 14 | 15 | 16 | // Transferring some tokens to the fees account 17 | // since tokens from eosio will not be directly accepted as contributions to 18 | // the bpay contract 19 | transfer( config::system_account_name, fees, core_sym::from_string("100000.0000"), config::system_account_name ); 20 | 21 | 22 | // Setting up the producers, standby and inactive producers, and voting them in 23 | setup_producer_accounts({standby, inactive}); 24 | auto producer_names = active_and_vote_producers(); 25 | 26 | BOOST_REQUIRE_EQUAL( success(), regproducer(standby) ); 27 | BOOST_REQUIRE_EQUAL( success(), regproducer(inactive) ); 28 | vector top_producers_and_inactive = {inactive}; 29 | top_producers_and_inactive.insert( top_producers_and_inactive.end(), producer_names.begin(), producer_names.begin()+21 ); 30 | 31 | BOOST_REQUIRE_EQUAL( success(), vote( voter, top_producers_and_inactive ) ); 32 | produce_blocks( 250 ); 33 | 34 | 35 | BOOST_REQUIRE_EQUAL( 0, get_producer_info( standby )["unpaid_blocks"].as() ); 36 | BOOST_REQUIRE_EQUAL( get_producer_info( producer_names[0] )["unpaid_blocks"].as() > 0, true ); 37 | 38 | // TODO: Check nothing happened here, no rewards since it comes from system account 39 | 40 | asset rewards_sent = core_sym::from_string("1000.0000"); 41 | transfer( fees, bpay, rewards_sent, fees); 42 | 43 | // rewards / 21 44 | asset balance_per_producer = core_sym::from_string("47.6190"); 45 | 46 | auto rewards = get_bpay_rewards(producer_names[0]); 47 | 48 | // bp.inactive is still active, so should be included in the rewards 49 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(inactive)["quantity"].as(), balance_per_producer ); 50 | // Random sample 51 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(producer_names[11])["quantity"].as(), balance_per_producer ); 52 | 53 | 54 | // Deactivating a producer 55 | BOOST_REQUIRE_EQUAL( success(), push_action(config::system_account_name, "rmvproducer"_n, mvo()("producer", inactive) ) ); 56 | BOOST_REQUIRE_EQUAL( false, get_producer_info( inactive )["is_active"].as() ); 57 | 58 | transfer( fees, bpay, rewards_sent, fees); 59 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(inactive)["quantity"].as(), balance_per_producer ); 60 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(producer_names[11])["quantity"].as(), core_sym::from_string("95.2380") ); 61 | 62 | // BP should be able to claim their rewards 63 | { 64 | auto prod = producer_names[11]; 65 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_balance( prod ) ); 66 | BOOST_REQUIRE_EQUAL( success(), bpay_claimrewards( prod ) ); 67 | BOOST_REQUIRE_EQUAL( core_sym::from_string("95.2380"), get_balance( prod ) ); 68 | BOOST_REQUIRE_EQUAL( true, get_bpay_rewards(prod).is_null() ); 69 | 70 | // should still have rewards for another producer 71 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(producer_names[10])["quantity"].as(), core_sym::from_string("95.2380") ); 72 | } 73 | 74 | // Should be able to claim rewards from a producer that is no longer active 75 | { 76 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_balance( inactive ) ); 77 | BOOST_REQUIRE_EQUAL( success(), bpay_claimrewards( inactive ) ); 78 | BOOST_REQUIRE_EQUAL( core_sym::from_string("47.6190"), get_balance( inactive ) ); 79 | BOOST_REQUIRE_EQUAL( true, get_bpay_rewards(inactive).is_null() ); 80 | } 81 | 82 | // Should not have rewards for a producer that was never active 83 | { 84 | BOOST_REQUIRE_EQUAL( true, get_bpay_rewards(standby).is_null() ); 85 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_balance( standby ) ); 86 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("no rewards to claim"), bpay_claimrewards( standby ) ); 87 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_balance( standby ) ); 88 | } 89 | 90 | // Tokens transferred from the eosio account should be ignored 91 | { 92 | transfer( config::system_account_name, bpay, rewards_sent, config::system_account_name ); 93 | BOOST_REQUIRE_EQUAL( get_bpay_rewards(producer_names[10])["quantity"].as(), core_sym::from_string("95.2380") ); 94 | } 95 | 96 | 97 | 98 | } FC_LOG_AND_RETHROW() 99 | 100 | 101 | BOOST_AUTO_TEST_SUITE_END() -------------------------------------------------------------------------------- /tests/eosio.fees_tests.cpp: -------------------------------------------------------------------------------- 1 | #include "eosio.system_tester.hpp" 2 | 3 | using namespace eosio_system; 4 | 5 | BOOST_AUTO_TEST_SUITE(eosio_fees_tests); 6 | 7 | BOOST_FIXTURE_TEST_CASE( fees_with_rex, eosio_system_tester ) try { 8 | // init REX 9 | const std::vector accounts = { "alice"_n }; 10 | const account_name alice = accounts[0]; 11 | const asset init_balance = core_sym::from_string("1000.0000"); 12 | setup_rex_accounts( accounts, init_balance ); 13 | buyrex( alice, core_sym::from_string("10.0000")); 14 | 15 | // manual token transfer to fees account 16 | const asset fees_before = get_balance( "eosio.fees" ); 17 | const asset rex_before = get_balance( "eosio.rex" ); 18 | const asset eosio_before = get_balance( "eosio" ); 19 | 20 | const asset fee = core_sym::from_string("100.0000"); 21 | transfer( config::system_account_name, "eosio.fees"_n, fee, config::system_account_name ); 22 | 23 | const asset fees_after = get_balance( "eosio.fees" ); 24 | const asset rex_after = get_balance( "eosio.rex" ); 25 | const asset eosio_after = get_balance( "eosio" ); 26 | 27 | BOOST_REQUIRE_EQUAL( fees_before, fees_after ); 28 | BOOST_REQUIRE_EQUAL( rex_before + fee, rex_after ); 29 | BOOST_REQUIRE_EQUAL( eosio_before - fee, eosio_after ); 30 | 31 | } FC_LOG_AND_RETHROW() 32 | 33 | BOOST_FIXTURE_TEST_CASE( fees_without_rex, eosio_system_tester ) try { 34 | // manual token transfer to fees account 35 | const asset fees_before = get_balance( "eosio.fees" ); 36 | const asset rex_before = get_balance( "eosio.rex" ); 37 | const asset eosio_before = get_balance( "eosio" ); 38 | 39 | const asset fee = core_sym::from_string("100.0000"); 40 | transfer( config::system_account_name, "eosio.fees"_n, fee, config::system_account_name ); 41 | 42 | const asset fees_after = get_balance( "eosio.fees" ); 43 | const asset rex_after = get_balance( "eosio.rex" ); 44 | const asset eosio_after = get_balance( "eosio" ); 45 | 46 | BOOST_REQUIRE_EQUAL( fees_before + fee, fees_after ); 47 | BOOST_REQUIRE_EQUAL( rex_before, rex_after ); 48 | BOOST_REQUIRE_EQUAL( eosio_before - fee, eosio_after ); 49 | 50 | } FC_LOG_AND_RETHROW() 51 | 52 | 53 | BOOST_AUTO_TEST_SUITE_END() 54 | -------------------------------------------------------------------------------- /tests/eosio.system_rex_matured_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "eosio.system_tester.hpp" 4 | 5 | using namespace eosio_system; 6 | 7 | BOOST_AUTO_TEST_SUITE(eosio_system_rex_tests) 8 | 9 | bool within_error(int64_t a, int64_t b, int64_t err) { return std::abs(a - b) <= err; }; 10 | bool within_one(int64_t a, int64_t b) { return within_error(a, b, 1); } 11 | 12 | BOOST_FIXTURE_TEST_CASE( buy_sell_matured_rex, eosio_system_tester ) try { 13 | // @param num_of_maturity_buckets - used to calculate maturity time of purchase REX tokens from end of the day UTC. 14 | // @param sell_matured_rex - if true, matured REX is sold immediately. 15 | // @param buy_rex_to_savings - if true, buying REX is moved immediately to REX savings. 16 | // 17 | // https://github.com/VaultaFoundation/system-contracts/issues/132 18 | // https://github.com/VaultaFoundation/system-contracts/issues/134 19 | // https://github.com/VaultaFoundation/system-contracts/issues/135 20 | 21 | // setup accounts 22 | const int64_t ratio = 10000; 23 | const asset init_rent = core_sym::from_string("20000.0000"); 24 | const asset init_balance = core_sym::from_string("1000.0000"); 25 | const std::vector accounts = { "alice"_n, "bob"_n, "charly"_n, "david"_n, "mark"_n }; 26 | account_name alice = accounts[0], bob = accounts[1], charly = accounts[2], david = accounts[3], mark = accounts[4]; 27 | setup_rex_accounts( accounts, init_balance ); 28 | 29 | 30 | // 1. set `num_of_maturity_buckets=21` to test increasing maturity time of buying REX tokens. 31 | BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, false, false ) ); 32 | BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( alice, core_sym::from_string("2.5000") ) ); 33 | produce_blocks(2); 34 | produce_block(fc::days(5)); 35 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( alice, asset::from_string("25000.0000 REX") ) ); 36 | produce_block(fc::days(16)); 37 | 38 | BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( alice, asset::from_string("25000.0000 REX") ) ); 39 | BOOST_REQUIRE_EQUAL( success(), buyrex( alice, core_sym::from_string("13.0000") ) ); 40 | BOOST_REQUIRE_EQUAL( core_sym::from_string("13.0000"), get_rex_vote_stake( alice ) ); 41 | BOOST_REQUIRE_EQUAL( success(), buyrex( alice, core_sym::from_string("17.0000") ) ); 42 | BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), get_rex_vote_stake( alice ) ); 43 | BOOST_REQUIRE_EQUAL( core_sym::from_string("970.0000"), get_rex_fund(alice) ); 44 | BOOST_REQUIRE_EQUAL( get_rex_balance(alice).get_amount(), ratio * asset::from_string("30.0000 REX").get_amount() ); 45 | auto rex_pool = get_rex_pool(); 46 | BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), rex_pool["total_lendable"].as() ); 47 | BOOST_REQUIRE_EQUAL( core_sym::from_string("30.0000"), rex_pool["total_unlent"].as() ); 48 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), rex_pool["total_lent"].as() ); 49 | BOOST_REQUIRE_EQUAL( init_rent, rex_pool["total_rent"].as() ); 50 | BOOST_REQUIRE_EQUAL( get_rex_balance(alice), rex_pool["total_rex"].as() ); 51 | 52 | // 2. set `sell_matured_rex=true` and `buy_rex_to_savings=false` to test buying REX without moving it to REX savings 53 | BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, true, false ) ); 54 | BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( bob, core_sym::from_string("2.5000") ) ); 55 | produce_blocks(2); 56 | produce_block(fc::days(5)); 57 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( bob, asset::from_string("25000.0000 REX") ) ); 58 | produce_block(fc::days(16)); 59 | BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_rex_vote_stake( bob ) ); 60 | BOOST_REQUIRE_EQUAL( asset::from_string("10000.0000 REX"), get_buyrex_result( bob, core_sym::from_string("1.0000") ) ); // will also triggers sell matured REX 61 | BOOST_REQUIRE_EQUAL( core_sym::from_string("1.0000"), get_rex_vote_stake( bob ) ); 62 | 63 | // 3. set `sell_matured_rex=false` and `buy_rex_to_savings=true` to test selling matured REX 64 | BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, false, true ) ); 65 | BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( charly, core_sym::from_string("2.5000") ) ); // when buying REX, it will automatically be moved to REX savings 66 | BOOST_REQUIRE_EQUAL( success(), mvfrsavings( charly, asset::from_string("25000.0000 REX") ) ); // move REX from savings to initiate matured REX unstaking process 67 | produce_blocks(2); 68 | produce_block(fc::days(5)); 69 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( charly, asset::from_string("25000.0000 REX") ) ); 70 | produce_block(fc::days(16)); 71 | BOOST_REQUIRE_EQUAL( success(), updaterex( charly ) ); // triggers sell matured REX (any REX action causes sell matured REX) 72 | BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( charly, asset::from_string("25000.0000 REX") ) ); 73 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_rex_vote_stake( charly ) ); 74 | BOOST_REQUIRE_EQUAL( init_balance, get_rex_fund( charly ) ); 75 | 76 | // 4. legacy holders with matured REX 77 | BOOST_REQUIRE_EQUAL( success(), setrexmature( 5, false, false ) ); 78 | BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( david, core_sym::from_string("2.5000") ) ); // legacy 5 days maturity 79 | BOOST_REQUIRE_EQUAL( asset::from_string("25000.0000 REX"), get_buyrex_result( mark, core_sym::from_string("2.5000") ) ); 80 | produce_blocks(2); 81 | produce_block(fc::days(5)); 82 | BOOST_REQUIRE_EQUAL( success(), setrexmature( 21, true, true ) ); 83 | BOOST_REQUIRE_EQUAL( asset::from_string("10000.0000 REX"), get_buyrex_result( david, core_sym::from_string("1.0000") ) ); // new 21 days maturity & triggers sell matured REX 84 | 85 | // 4.1. Test selling less than all their matured rex, and having all of their already matured rex sold regardless 86 | BOOST_REQUIRE_EQUAL( core_sym::from_string("2.5000"), get_sellrex_result( mark, asset::from_string("1.0000 REX") ) ); 87 | 88 | BOOST_REQUIRE_EQUAL( success(), mvfrsavings( david, asset::from_string("10000.0000 REX") ) ); // must move REX from savings to initiate matured REX unstaking process 89 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( david, asset::from_string("25000.0000 REX") ) ); // already sold when previously buying REX 90 | produce_blocks(2); 91 | produce_block(fc::days(5)); 92 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("insufficient available rex"), sellrex( david, asset::from_string("10000.0000 REX") ) ); // 21 day REX not matured yet 93 | produce_blocks(2); 94 | produce_block(fc::days(21)); 95 | BOOST_REQUIRE_EQUAL( core_sym::from_string("1.0000"), get_sellrex_result( david, asset::from_string("10000.0000 REX") ) ); 96 | BOOST_REQUIRE_EQUAL( core_sym::from_string("0.0000"), get_rex_vote_stake( david ) ); 97 | BOOST_REQUIRE_EQUAL( init_balance, get_rex_fund( david ) ); 98 | 99 | // 5.0 Instant maturation 100 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("num_of_maturity_buckets must be positive"), setrexmature( 0, true, true ) ); 101 | 102 | 103 | } FC_LOG_AND_RETHROW() 104 | 105 | BOOST_AUTO_TEST_SUITE_END() 106 | -------------------------------------------------------------------------------- /tests/eosio.system_schedules_tests.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "eosio.system_tester.hpp" 3 | 4 | using namespace eosio_system; 5 | 6 | BOOST_AUTO_TEST_SUITE(eosio_system_vesting_tests) 7 | 8 | BOOST_FIXTURE_TEST_CASE(set_schedules, eosio_system_tester) try { 9 | 10 | 11 | auto check_schedule = [&](time_point_sec time, double rate){ 12 | auto schedule = get_vesting_schedule(time.sec_since_epoch()); 13 | REQUIRE_MATCHING_OBJECT( schedule, mvo() 14 | ("start_time", time) 15 | ("continuous_rate", rate) 16 | ); 17 | }; 18 | 19 | const std::vector accounts = { "alice"_n }; 20 | create_accounts_with_resources( accounts ); 21 | const account_name alice = accounts[0]; 22 | 23 | const uint32_t YEAR = 86400 * 365; 24 | uint32_t initial_start_time = control->pending_block_time().sec_since_epoch(); // 1577836853 (2020-01-01T00:00:56.000Z) 25 | time_point_sec start_time = time_point_sec(initial_start_time); 26 | 27 | 28 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("continuous_rate can't be over 100%"), setschedule(start_time, 1.00001) ); 29 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("continuous_rate can't be negative"), setschedule(start_time, -1) ); 30 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("schedule not found"), delschedule(start_time) ); 31 | 32 | // action validation 33 | BOOST_REQUIRE_EQUAL( success(), setschedule(time_point_sec(0), 0.05) ); 34 | BOOST_REQUIRE_EQUAL( success(), setschedule(start_time, 0.05) ); 35 | check_schedule(start_time, 0.05); 36 | 37 | // allow override existing schedules 38 | BOOST_REQUIRE_EQUAL( success(), setschedule(start_time, 0.02) ); 39 | check_schedule(start_time, 0.02); 40 | 41 | 42 | // Should be able to delete schedules, even in the past 43 | BOOST_REQUIRE_EQUAL( success(), delschedule(start_time) ); 44 | BOOST_REQUIRE_EQUAL( success(), delschedule(time_point_sec(0)) ); 45 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("schedule not found"), delschedule(start_time) ); 46 | 47 | // Resetting timers to make math clean 48 | initial_start_time = control->pending_block_time().sec_since_epoch(); 49 | start_time = time_point_sec(initial_start_time); 50 | 51 | 52 | // // set 4 future schedules 53 | BOOST_REQUIRE_EQUAL( success(), setschedule(start_time, 0.02) ); 54 | check_schedule(start_time, 0.02); 55 | BOOST_REQUIRE_EQUAL( success(), setschedule(time_point_sec(initial_start_time + YEAR * 4), 0.01) ); 56 | check_schedule(time_point_sec(initial_start_time + YEAR * 4), 0.01); 57 | BOOST_REQUIRE_EQUAL( success(), setschedule(time_point_sec(initial_start_time + YEAR * 8), 0.005) ); 58 | check_schedule(time_point_sec(initial_start_time + YEAR * 8), 0.005); 59 | BOOST_REQUIRE_EQUAL( success(), setschedule(time_point_sec(initial_start_time + YEAR * 12), 0.0005) ); 60 | check_schedule(time_point_sec(initial_start_time + YEAR * 12), 0.0005); 61 | BOOST_REQUIRE_EQUAL( success(), setschedule(time_point_sec(initial_start_time + YEAR * 13), 0) ); 62 | check_schedule(time_point_sec(initial_start_time + YEAR * 13), 0); 63 | 64 | // current state prior to first schedule change execution 65 | const double before = get_global_state4()["continuous_rate"].as_double(); 66 | BOOST_REQUIRE_EQUAL( before, 0.048790164169432007 ); // 5% continuous rate 67 | 68 | BOOST_REQUIRE_EQUAL( success(), execschedule(alice) ); 69 | BOOST_REQUIRE_EQUAL( get_global_state4()["continuous_rate"].as_double(), 0.02 ); 70 | 71 | // Cannot execute schedule before its time is due 72 | // (we did 6 actions so we're late 3s late) 73 | auto late = fc::seconds(3); 74 | produce_block( fc::seconds(YEAR * 4) - fc::seconds(1) - late ); // advance to year 4 75 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("no schedule to execute"), execschedule(alice) ); 76 | 77 | // Can execute this schedule 1 second after, as that is its time 78 | produce_block( fc::seconds(1) ); // advance to year 4 79 | BOOST_REQUIRE_EQUAL( control->pending_block_time().sec_since_epoch(), initial_start_time + YEAR * 4 ); // 2024-01-01T00:00 80 | BOOST_REQUIRE_EQUAL( success(), execschedule(alice) ); 81 | BOOST_REQUIRE_EQUAL( get_global_state4()["continuous_rate"].as_double(), 0.01 ); // 1% continuous rate 82 | 83 | produce_block( fc::days(365 * 4) ); // advanced to year 8 84 | BOOST_REQUIRE_EQUAL( success(), execschedule(alice) ); 85 | BOOST_REQUIRE_EQUAL( get_global_state4()["continuous_rate"].as_double(), 0.005 ); // 0.5% continuous rate 86 | 87 | produce_block( fc::days(365 * 4) ); // advanced to year 12 88 | BOOST_REQUIRE_EQUAL( success(), execschedule(alice) ); 89 | BOOST_REQUIRE_EQUAL( get_global_state4()["continuous_rate"].as_double(), 0.0005 ); // 0.05% continuous rate 90 | 91 | produce_block( fc::days(365 * 1) ); // advanced to year 13 92 | BOOST_REQUIRE_EQUAL( success(), execschedule(alice) ); 93 | BOOST_REQUIRE_EQUAL( get_global_state4()["continuous_rate"].as_double(), 0.0 ); // 0% continuous rate 94 | 95 | // no more schedules 96 | BOOST_REQUIRE_EQUAL( wasm_assert_msg("no schedule to execute"), execschedule(alice) ); 97 | 98 | } FC_LOG_AND_RETHROW() 99 | 100 | BOOST_AUTO_TEST_SUITE_END() 101 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "eosio.system_tester.hpp" 13 | 14 | using namespace eosio_system; 15 | #define BOOST_TEST_STATIC_LINK 16 | 17 | void translate_fc_exception(const fc::exception &e) { 18 | std::cerr << "\033[33m" << e.to_detail_string() << "\033[0m" << std::endl; 19 | BOOST_TEST_FAIL("Caught Unexpected Exception"); 20 | } 21 | 22 | boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { 23 | // Turn off blockchain logging if no --verbose parameter is not added 24 | // To have verbose enabled, call "tests/chain_test -- --verbose" 25 | bool is_verbose = false; 26 | std::string verbose_arg = "--verbose"; 27 | for (int i = 0; i < argc; i++) { 28 | if (verbose_arg == argv[i]) { 29 | is_verbose = true; 30 | break; 31 | } 32 | } 33 | 34 | if(is_verbose) { 35 | fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::debug); 36 | } else { 37 | fc::logger::get(DEFAULT_LOGGER).set_log_level(fc::log_level::off); 38 | } 39 | 40 | // Register fc::exception translator 41 | boost::unit_test::unit_test_monitor.template register_exception_translator(&translate_fc_exception); 42 | 43 | std::srand(time(NULL)); 44 | std::cout << "Random number generator seeded to " << time(NULL) << std::endl; 45 | return nullptr; 46 | } 47 | -------------------------------------------------------------------------------- /tests/test_contracts/exchange.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/tests/test_contracts/exchange.wasm -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.2.1/eosio.msig/Readme.txt: -------------------------------------------------------------------------------- 1 | Compiled with 2 | eosio.contracts: ee6415b0d3f9cff3bafebf98b2e06b80545dfa36 3 | eosio.wasmsdk: 0d4befeee7abbef1db775b2e8833f7db8fca7ad2 (v1.1.1), CORE_SYMBOL_NAME = "SYS" 4 | -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.2.1/eosio.msig/eosio.msig.abi: -------------------------------------------------------------------------------- 1 | { 2 | "version": "eosio::abi/1.0", 3 | "types": [{ 4 | "new_type_name": "account_name", 5 | "type": "name" 6 | },{ 7 | "new_type_name": "permission_name", 8 | "type": "name" 9 | },{ 10 | "new_type_name": "action_name", 11 | "type": "name" 12 | }], 13 | "structs": [{ 14 | "name": "permission_level", 15 | "base": "", 16 | "fields": [ 17 | {"name": "actor", "type": "account_name"}, 18 | {"name": "permission", "type": "permission_name"} 19 | ] 20 | },{ 21 | "name": "action", 22 | "base": "", 23 | "fields": [ 24 | {"name": "account", "type": "account_name"}, 25 | {"name": "name", "type": "action_name"}, 26 | {"name": "authorization", "type": "permission_level[]"}, 27 | {"name": "data", "type": "bytes"} 28 | ] 29 | },{ 30 | "name": "transaction_header", 31 | "base": "", 32 | "fields": [ 33 | {"name": "expiration", "type": "time_point_sec"}, 34 | {"name": "ref_block_num", "type": "uint16"}, 35 | {"name": "ref_block_prefix", "type": "uint32"}, 36 | {"name": "max_net_usage_words", "type": "varuint32"}, 37 | {"name": "max_cpu_usage_ms", "type": "uint8"}, 38 | {"name": "delay_sec", "type": "varuint32"} 39 | ] 40 | },{ 41 | "name": "extension", 42 | "base": "", 43 | "fields": [ 44 | {"name": "type", "type" : "uint16" }, 45 | {"name": "data", "type": "bytes"} 46 | ] 47 | },{ 48 | "name": "transaction", 49 | "base": "transaction_header", 50 | "fields": [ 51 | {"name": "context_free_actions", "type": "action[]"}, 52 | {"name": "actions", "type": "action[]"}, 53 | {"name": "transaction_extensions", "type": "extension[]"} 54 | ] 55 | },{ 56 | "name": "propose", 57 | "base": "", 58 | "fields": [ 59 | {"name":"proposer", "type":"account_name"}, 60 | {"name":"proposal_name", "type":"name"}, 61 | {"name":"requested", "type":"permission_level[]"}, 62 | {"name":"trx", "type":"transaction"} 63 | ] 64 | },{ 65 | "name": "approve", 66 | "base": "", 67 | "fields": [ 68 | {"name":"proposer", "type":"account_name"}, 69 | {"name":"proposal_name", "type":"name"}, 70 | {"name":"level", "type":"permission_level"} 71 | ] 72 | },{ 73 | "name": "unapprove", 74 | "base": "", 75 | "fields": [ 76 | {"name":"proposer", "type":"account_name"}, 77 | {"name":"proposal_name", "type":"name"}, 78 | {"name":"level", "type":"permission_level"} 79 | ] 80 | },{ 81 | "name": "cancel", 82 | "base": "", 83 | "fields": [ 84 | {"name":"proposer", "type":"account_name"}, 85 | {"name":"proposal_name", "type":"name"}, 86 | {"name":"canceler", "type":"account_name"} 87 | ] 88 | },{ 89 | "name": "exec", 90 | "base": "", 91 | "fields": [ 92 | {"name":"proposer", "type":"account_name"}, 93 | {"name":"proposal_name", "type":"name"}, 94 | {"name":"executer", "type":"account_name"} 95 | ] 96 | },{ 97 | "name": "proposal", 98 | "base": "", 99 | "fields": [ 100 | {"name": "proposal_name", "type": "name"}, 101 | {"name": "packed_transaction", "type": "bytes"} 102 | ] 103 | },{ 104 | "name": "approvals_info", 105 | "base": "", 106 | "fields": [ 107 | {"name": "proposal_name", "type": "name"}, 108 | {"name": "requested_approvals", "type": "permission_level[]"}, 109 | {"name": "provided_approvals", "type": "permission_level[]"} 110 | ] 111 | } 112 | ], 113 | "actions": [{ 114 | "name": "propose", 115 | "type": "propose", 116 | "ricardian_contract": "" 117 | },{ 118 | "name": "approve", 119 | "type": "approve", 120 | "ricardian_contract": "" 121 | },{ 122 | "name": "unapprove", 123 | "type": "unapprove", 124 | "ricardian_contract": "" 125 | }, { 126 | "name": "cancel", 127 | "type": "cancel", 128 | "ricardian_contract": "" 129 | }, { 130 | "name": "exec", 131 | "type": "exec", 132 | "ricardian_contract": "" 133 | } 134 | 135 | ], 136 | "tables": [{ 137 | "name": "proposal", 138 | "type": "proposal", 139 | "index_type": "i64", 140 | "key_names" : ["proposal_name"], 141 | "key_types" : ["name"] 142 | },{ 143 | "name": "approvals", 144 | "type": "approvals_info", 145 | "index_type": "i64", 146 | "key_names" : ["proposal_name"], 147 | "key_types" : ["name"] 148 | } 149 | ], 150 | "ricardian_clauses": [], 151 | "abi_extensions": [] 152 | } 153 | -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.2.1/eosio.msig/eosio.msig.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/tests/test_contracts/old_versions/v1.2.1/eosio.msig/eosio.msig.wasm -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.2.1/eosio.system/README.txt: -------------------------------------------------------------------------------- 1 | Compiled with 2 | eosio.contracts: bf28f8bbf9ee753966c95c586906e82d72f9dfac (v1.2.1) 3 | eosio.wasmsdk: 2c106a018f2e69d34325ef2376cf085426068e93, CORE_SYMBOL_NAME = "SYS" 4 | -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.2.1/eosio.system/eosio.system.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/tests/test_contracts/old_versions/v1.2.1/eosio.system/eosio.system.wasm -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.8.3/eosio.system/README.txt: -------------------------------------------------------------------------------- 1 | Compiled with 2 | eosio.contracts: 7109f002fa9afff18edcafce5c32b224a21eef98 (v1.8.3) 3 | eosio.cdt: 263e41cbb3e58dca71117401f43be104f1e58ae4 (v1.6.3) 4 | -------------------------------------------------------------------------------- /tests/test_contracts/old_versions/v1.8.3/eosio.system/eosio.system.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/tests/test_contracts/old_versions/v1.8.3/eosio.system/eosio.system.wasm -------------------------------------------------------------------------------- /tests/test_contracts/reject_all.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VaultaFoundation/system-contracts/75fd36b56da410e767d950a47c2253650b14ea9d/tests/test_contracts/reject_all.wasm -------------------------------------------------------------------------------- /tests/test_symbol.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define CORE_SYM_NAME "TST" 4 | #define CORE_SYM_PRECISION 4 5 | 6 | #define _STRINGIZE1(x) #x 7 | #define _STRINGIZE2(x) _STRINGIZE1(x) 8 | 9 | #define CORE_SYM_STR ( _STRINGIZE2(CORE_SYM_PRECISION) "," CORE_SYM_NAME ) 10 | #define CORE_SYM ( ::eosio::chain::string_to_symbol_c( CORE_SYM_PRECISION, CORE_SYM_NAME ) ) 11 | 12 | struct core_sym { 13 | static inline eosio::chain::asset from_string(const std::string& s) { 14 | return eosio::chain::asset::from_string(s + " " CORE_SYM_NAME); 15 | } 16 | }; 17 | --------------------------------------------------------------------------------