├── .babelrc ├── .circleci ├── config.yml └── install-yarn.sh ├── .dockerignore ├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .solcover.js ├── .soliumignore ├── .soliumrc.json ├── CodeStyle.md ├── Dockerfile ├── ETODEPLOY.md ├── ICBM.md ├── INVEST.md ├── LICENSE.md ├── Makefile ├── README.md ├── bin ├── solc.4.24 ├── solc.4.25 └── solc.4.26 ├── cmdLinePKProvider.js ├── consolePKProvider.js ├── contracts ├── AccessControl │ ├── AccessControlled.sol │ ├── IAccessControlled.sol │ ├── IAccessPolicy.sol │ ├── RoleBasedAccessPolicy.sol │ └── StandardRoles.sol ├── AccessRoles.sol ├── Agreement.sol ├── Company │ ├── ControllerDividends.sol │ ├── ControllerETO.sol │ ├── ControllerGeneralInformation.sol │ ├── ControllerGovernanceEngine.sol │ ├── ControllerGovernanceToken.sol │ ├── EquityToken.sol │ ├── EquityTokenMetadata.sol │ ├── EquityTokenholderRights.sol │ ├── Extras │ │ ├── ESOP │ │ │ ├── ESOP.sol │ │ │ ├── ESOPTypes.sol │ │ │ ├── EmployeesList.sol │ │ │ ├── IESOPOptionsConverter.sol │ │ │ └── OptionsCalculator.sol │ │ ├── ExitController.sol │ │ ├── GranularTransferController.sol │ │ └── RegDTransferController.sol │ ├── Gov.sol │ ├── IControlledToken.sol │ ├── IControllerDividends.sol │ ├── IControllerETO.sol │ ├── IControllerGeneralInformation.sol │ ├── IControllerGovernance.sol │ ├── IControllerGovernanceEngine.sol │ ├── IControllerGovernanceToken.sol │ ├── IEquityToken.sol │ ├── IEquityTokenController.sol │ ├── ITokenholderRights.sol │ ├── MGovernanceObserver.sol │ ├── ShareholderRights.sol │ └── SingleEquityTokenController.sol ├── Compat │ └── ERC223LegacyCallbackCompat.sol ├── Deprecations │ ├── IControllerGovernance_v1_3.sol │ ├── IEquityToken_v0.sol │ ├── README.md │ └── deprecations.json ├── ETO │ ├── ETOCommitment.sol │ ├── ETODurationTerms.sol │ ├── ETOTerms.sol │ ├── ETOTermsConstraints.sol │ ├── ETOTimedStateMachine.sol │ ├── ETOTokenTerms.sol │ ├── ICommitment.sol │ ├── IETOCommitment.sol │ ├── IETOCommitmentObserver.sol │ ├── IETOCommitmentStates.sol │ └── METOStateMachineObserver.sol ├── EthereumForkArbiter.sol ├── FeeDisbursal │ ├── FeeDisbursal.sol │ └── FeeDisbursalController.sol ├── ICBM │ ├── Commitment │ │ ├── ICBMCommitment.sol │ │ ├── ICBMStateMachine.sol │ │ └── ICBMTimedStateMachine.sol │ ├── ICBMEtherToken.sol │ ├── ICBMEuroToken.sol │ ├── ICBMEuroTokenMigrationTarget.sol │ ├── ICBMLockedAccount.sol │ ├── ICBMLockedAccountMigration.sol │ ├── ICBMRoles.sol │ ├── IMigrationSource.sol │ ├── IMigrationTarget.sol │ ├── LockedAccount.sol │ ├── MigrationSource.sol │ ├── MigrationTarget.sol │ └── TimeSource.sol ├── Identity │ ├── IIdentityRegistry.sol │ └── IdentityRegistry.sol ├── IsContract.sol ├── KnownContracts.sol ├── KnownInterfaces.sol ├── Math.sol ├── Neumark.sol ├── NeumarkIssuanceCurve.sol ├── PaymentTokens │ ├── EtherToken.sol │ ├── EuroToken.sol │ └── EuroTokenController.sol ├── PlatformTerms.sol ├── Reclaimable.sol ├── Serialization.sol ├── SimpleExchange.sol ├── Snapshot │ ├── Daily.sol │ ├── DailyAndSnapshotable.sol │ ├── Extras │ │ ├── EveryBlock.sol │ │ └── Snapshotable.sol │ ├── MSnapshotPolicy.sol │ └── Snapshot.sol ├── SnapshotToken │ ├── BasicSnapshotToken.sol │ ├── BasicToken.sol │ ├── Extensions │ │ ├── Disbursal.sol │ │ ├── ISnapshotableToken.sol │ │ └── Vote.sol │ ├── Helpers │ │ ├── MTokenAllowanceController.sol │ │ ├── MTokenController.sol │ │ ├── MTokenMint.sol │ │ ├── MTokenTransfer.sol │ │ ├── MTokenTransferController.sol │ │ ├── TokenAllowance.sol │ │ ├── TokenMetadata.sol │ │ └── TrustlessTokenController.sol │ ├── MintableSnapshotToken.sol │ ├── README.md │ ├── StandardSnapshotToken.sol │ ├── StandardToken.sol │ └── ncd.png ├── Standards │ ├── IAgreement.sol │ ├── IBasicToken.sol │ ├── IClonedTokenParent.sol │ ├── IContractId.sol │ ├── IERC20Allowance.sol │ ├── IERC20Token.sol │ ├── IERC223Callback.sol │ ├── IERC223LegacyCallback.sol │ ├── IERC223Token.sol │ ├── IERC677Allowance.sol │ ├── IERC677Callback.sol │ ├── IERC677Token.sol │ ├── IEthereumForkArbiter.sol │ ├── IFeeDisbursal.sol │ ├── IFeeDisbursalController.sol │ ├── IGasExchange.sol │ ├── IMigrationChain.sol │ ├── IPlatformPortfolio.sol │ ├── ISnapshotable.sol │ ├── ITokenController.sol │ ├── ITokenControllerHook.sol │ ├── ITokenExchangeRateOracle.sol │ ├── ITokenMetadata.sol │ ├── ITokenSnapshots.sol │ └── IWithdrawableToken.sol ├── Universe.sol ├── VotingCenter │ ├── IVotingCenter.sol │ ├── IVotingController.sol │ ├── IVotingObserver.sol │ ├── VotingCenter.sol │ ├── VotingController.sol │ └── VotingProposal.sol └── test │ ├── Company │ ├── MockEquityToken.sol │ ├── MockSingleEquityTokenController.sol │ ├── TestControllerGovernanceEngine.sol │ └── TestMockableEquityTokenController.sol │ ├── CurveGas.sol │ ├── ETO │ ├── MockETOCommitment.sol │ ├── MockETOTermsConstraints.sol │ ├── MockUncheckedETOTokenTerms.sol │ ├── NullCommitment.sol │ └── TestETOCommitmentSingleTokenController.sol │ ├── ForceEther.sol │ ├── ICBM │ ├── MockICBMCommitment.sol │ ├── TestFeeDistributionPool.sol │ ├── TestICBMEuroTokenMigrationTarget.sol │ ├── TestICBMLockedAccountController.sol │ ├── TestICBMLockedAccountMigrationTarget.sol │ └── TestICBMTimedStateMachine.sol │ ├── MockSnapshotIdToken.sol │ ├── MockVotingCenter.sol │ ├── TestAccessControl.sol │ ├── TestAgreement.sol │ ├── TestDisburser.sol │ ├── TestERC223Callback.sol │ ├── TestERC223LegacyCallback.sol │ ├── TestERC677Callback.sol │ ├── TestIdentityRecord.sol │ ├── TestMath.sol │ ├── TestMockableTokenController.sol │ ├── TestNeumark.sol │ ├── TestNullContract.sol │ ├── TestReceiver.sol │ ├── TestReclaimable.sol │ ├── TestSender.sol │ ├── TestSnapshot.sol │ ├── TestSnapshotToken.sol │ ├── TestToken.sol │ ├── TestTokenControllerPassThrough.sol │ ├── TestUpdatedIdentityRecord.sol │ ├── TestVotingController.sol │ └── TestVotingObserver.sol ├── doc ├── Curve.ipynb ├── NEUcurveTestPoints.nb ├── NEUcurveTestPoints.pdf ├── agreementparity.png └── icbmcontracts.png ├── legal ├── NEUMARK TOKEN HOLDER AGREEMENT.docx ├── NEUMARK TOKEN HOLDER AGREEMENT.html ├── README.md ├── RESERVATION AGREEMENT.docx └── RESERVATION AGREEMENT.html ├── migrations ├── .eslintrc.json ├── 101_apply_fixtures.js ├── 102_fixtures_kyc.js ├── 103_ether_token_deposits.js ├── 104_euro_token_deposits.js ├── 105_migrate_locked_icbm_accounts.js ├── 106_deploy_fixture_commitments.js ├── 107_add_exit_contracts.js ├── 10_deploy_platform_permissions.js ├── 113_apply_payout_fixtures.js ├── 114_adds_various_transaction_fixtures.js ├── 115_add_post_investment_fixtures.js ├── 11_setup_platform.js ├── 12_deploy_fee_disbursal.js ├── 13_deploy_eto_terms_constraints.js ├── 14_new_disbursal_controller_for_eto_recycle.js ├── 15_deploy_sme_eto_li_constraints.js ├── 16_deploy_voting_center.js ├── 198_save_eto_constrains_fixtures_state.js ├── 199_save_account_fixtures_state.js ├── 1_initial_migration.js ├── 201_platform_finalize.js ├── 2_deploy_contracts.js ├── 3_deploy_permissions.js ├── 4_link_contracts.js ├── 5_amend_agreements.js ├── 6_relinquish_control.js ├── 7_distribute_ether_to_fixtures_accounts.js ├── 8_patch_icbm_state.js ├── 9_deploy_platform_contracts.js ├── config.js ├── deployConstraints.js ├── deployETO.js ├── fixtures │ ├── accounts.js │ ├── accounts.json │ ├── eto_terms.js │ ├── eto_terms_constraints.js │ └── etos.js ├── helpers.js └── migrateController.js ├── mocha.js ├── multiWalletProvider.js ├── nanoWeb3Provider.js ├── package.json ├── scripts ├── build.sh ├── cancelTx.js ├── deploy.sh ├── deployETO.js ├── deployETOTermsConstraints.js ├── deployWhitelist.js ├── fixtures │ ├── addFixture.js │ ├── getETOFixtureAddress.js │ ├── getFixture.js │ └── listFixtures.js ├── flatten.sh ├── getAddressFromLedger.js ├── helpers.js ├── inspectETO.js ├── investIntoETO.js ├── investIntoETOCheck.js ├── investIntoETOPrepare.js ├── solcs.sh ├── solctruffle.sh ├── test.sh ├── testrpc.sh └── verifyDeployment.js ├── test ├── .eslintrc.json ├── AccessControl.js ├── Agreement.js ├── Company │ ├── EquityToken.js │ ├── Extras │ │ ├── ExitController.js │ │ └── ExtraTokenControllers.js │ ├── SingleEquityTokenController.js │ ├── TestControllerGovernanceEngine.js │ ├── TokenholderRights.js │ └── bin │ │ └── legacyControllers.js ├── ETO │ ├── ETOCommitment.js │ ├── ETOTerms.js │ └── ETOTermsConstraints.js ├── EtherToken.js ├── EthereumForkArbiter.js ├── EuroToken.js ├── EuroTokenController.js ├── FeeDisbursal.js ├── ICBM │ ├── Commitment.js │ ├── EtherToken.js │ ├── EuroToken.js │ ├── LockedAccount.js │ ├── TimedStateMachine.js │ ├── commitmentState.js │ └── lockState.js ├── IdentityRegistry.js ├── LockedAccount.js ├── Math.js ├── Mock.js ├── Neumark.js ├── NeumarkIssuanceCurve.js ├── PlatformTerms.js ├── Reclaimable.js ├── SimpleExchange.js ├── Snapshot.js ├── SnapshotToken.js ├── Universe.js ├── VotingCenter.js ├── data │ ├── expectedCurveEuroAtIntegers.csv │ ├── expectedCurveEuroAtRandom.csv │ ├── expectedCurvePointsAtIntegers.csv │ ├── expectedCurvePointsAtRandom.csv │ └── expectedCurvePointsAtRandomLarge.csv ├── helpers │ ├── EVMThrow.js │ ├── artifacts.js │ ├── chaiWeb3.js │ ├── commitment.js │ ├── commitmentState.js │ ├── constants.js │ ├── createAccessPolicy.js │ ├── dataset.js │ ├── deployContracts.js │ ├── deployTerms.js │ ├── disbursal.js │ ├── events.js │ ├── evmCommands.js │ ├── forceEther.js │ ├── gasUtils.js │ ├── govState.js │ ├── govUtils.js │ ├── identityClaims.js │ ├── increaseTime.js │ ├── interfaceArtifacts.js │ ├── knownInterfaces.js │ ├── latestTime.js │ ├── mockReceiverTestCases.js │ ├── promiseUtils.js │ ├── registerSingletons.js │ ├── relayedVoteSigning.js │ ├── roles.js │ ├── snapshotTokenTestCases.js │ ├── termsConstants.js │ ├── tokenControllerTestCases.js │ ├── tokenTestCases.js │ ├── triState.js │ ├── unitConverter.js │ ├── utils.js │ └── voting.js ├── lockState.js └── setup.js ├── truffle.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ] 11 | ], 12 | "retainLines": true 13 | } 14 | -------------------------------------------------------------------------------- /.circleci/install-yarn.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | cd "$(dirname "$0")" 4 | 5 | source ~/.bashrc 6 | 7 | # setup node version 8 | nvm install 8 9 | nvm use 8 10 | nvm alias default 8 11 | 12 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 13 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 14 | 15 | sudo apt-get update && sudo apt-get install -y yarn 16 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | charset = utf-8 12 | indent_style = space 13 | indent_size = 2 14 | max_line_length = 100 15 | 16 | [**.js] 17 | indent_size = 2 18 | 19 | # Solidity requires four spaces 20 | [**.sol] 21 | indent_size = 4 22 | 23 | [{Makefile,**.mk}] 24 | # Use tabs for indentation (Makefiles require tabs) 25 | indent_style = tab 26 | 27 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier"], 3 | "plugins": ["prettier", "mocha"], 4 | "rules": { 5 | "prettier/prettier": ["error"], 6 | "import/no-named-as-default": ["off"], 7 | "no-await-in-loop": ["off"], 8 | "no-use-before-define": ["error", { "functions": false }], 9 | "no-unused-vars": ["error", { "argsIgnorePattern": "^_$" }], 10 | "no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"], 11 | "no-underscore-dangle": ["off"], 12 | "no-bitwise": ["off"], 13 | "import/prefer-default-export": ["off"], 14 | "mocha/no-exclusive-tests": "error", 15 | "max-len": ["error", { "code": 100, "ignoreComments": true, "ignoreStrings": true }], 16 | "one-var": ["off"], 17 | "func-names": ["off"] 18 | }, 19 | "env": { 20 | "node": true, 21 | "mocha": true 22 | }, 23 | "globals": { 24 | "artifacts": true, 25 | "contract": true, 26 | "assert": true, 27 | "web3": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Compiled output 12 | build 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directories 33 | node_modules 34 | jspm_packages 35 | 36 | # Optional npm cache directory 37 | .npm 38 | 39 | # Optional REPL history 40 | .node_repl_history 41 | 42 | # Cryptographic keys 43 | *.pem 44 | 45 | # Remove jetbrains 46 | .idea 47 | 48 | # Ignore jupyter / python notebooks 49 | .ipynb_checkpoints 50 | coverageEnv 51 | coverage.json 52 | platform-contracts-artifacts 53 | etos 54 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 8.17.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **.json 3 | build 4 | legal 5 | contracts 6 | package.json 7 | **.md 8 | **.sol 9 | platform-contracts-artifacts 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": false, 6 | "trailingComma": "all", 7 | "proseWrap": "always" 8 | } 9 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/VotingCenter/VotingCenter.sol 3 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": ["security"], 4 | "rules": { 5 | "quotes": ["error", "double"], 6 | "indentation": ["error", 4], 7 | "security/no-low-level-calls": "off", 8 | "security/no-inline-assembly": "off", 9 | "security/no-block-members": "off", 10 | "no-empty-blocks": "off", 11 | "no-constant": "off", 12 | "error-reason": "off" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CodeStyle.md: -------------------------------------------------------------------------------- 1 | # Code style 2 | 3 | Order within contracts: 4 | 5 | 1. Type declarations 6 | 2. Constants 7 | 3. Immutable state variables (Set only in constructor) 8 | 4. State variables 9 | 5. Events 10 | 6. Modifiers 11 | 7. Constructor 12 | 8. Fallback function 13 | 9. External functions (constant functions last) 14 | 10. Public funcions (constant functions last) 15 | 11. Internal functions (constant functions last) 16 | 12. Private functions (constant functions last) 17 | 18 | Order of operations within an external or public function: 19 | 20 | 1. `pure` Validate input (`require`) 21 | 2. `constant` Read state, compute and validate more (`require` and `assert`) 22 | 3. Write state (from here only `pure` operations allowed) (no `require` or `assert`) 23 | 4. Call external functions (`assert` allowed again) 24 | 5. Write logs 25 | 6. Return 26 | 27 | The critical section is between the first read and the last write. In this region the control flow 28 | needs to be extremely reliable. 29 | 30 | Abstract internal functions are used through a Mixin interface; a constract with an `M` prefix 31 | containing only abstract internal functions. 32 | 33 | Constants and immutable state variables are ALL_CAPS. Internal constants go before private ones. All 34 | constants are either internal or private. 35 | 36 | Mutable state variables are _camelCase with a 37 | `_`prefix. State variables should always be`private`or, when intended to be access by a subclass,`internal`. 38 | This is to avoid uncessary public functions cluthering the ABI, or accidental collision/overriding a 39 | state variable in a subclass. 40 | 41 | Don't use `uint`, always be explicit and use `uint256`. 42 | 43 | Only mutable state variables can start with `_`. In particular functions, arguments and variables do 44 | not. 45 | 46 | Log events start with `Log`. 47 | 48 | # References 49 | 50 | - [Solidity official style guide][docs] 51 | - [ConsenSys Best Practices][csbp] 52 | 53 | [docs]: https://solidity.readthedocs.io/en/develop/style-guide.html 54 | [csbp]: https://github.com/ConsenSys/smart-contract-best-practices 55 | 56 | # TODO 57 | 58 | Mark contracts Trusted or Untrusted. 59 | 60 | []: https://github.com/ConsenSys/smart-contract-best-practices#mark-untrusted-contracts 61 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8-alpine 2 | 3 | # Metadata 4 | LABEL org.label-schema.vendor="Neufund" \ 5 | org.label-schema.url="https://neufund.org" \ 6 | org.label-schema.name="Platform Contracts" \ 7 | org.label-schema.description="Platform smart contract and build + deploy pipeline" \ 8 | org.label-schema.version="0.0.1" \ 9 | org.label-schema.vcs-url="https://github.com/Neufund/platform-contracts" \ 10 | org.label-schema.docker.schema-version="1.0" 11 | 12 | RUN apk --update add git openssh make gcc g++ python bash && \ 13 | rm -rf /var/lib/apt/lists/* && \ 14 | rm /var/cache/apk/* 15 | # add full permissions to anyone as we intend to run commands on host users 16 | RUN mkdir -p /usr/src/platform-contracts && chmod 777 /usr/src/platform-contracts 17 | WORKDIR /usr/src/platform-contracts 18 | # only things required by yarn install 19 | ADD .babelrc package.json yarn.lock ./ 20 | RUN NODE_TLS_REJECT_UNAUTHORIZED=0 yarn --production 21 | # all other files 22 | ADD bin/solc.4.26 /usr/bin/ 23 | ADD scripts scripts 24 | RUN ./scripts/solctruffle.sh 25 | ADD contracts contracts 26 | RUN find ./contracts/ -exec touch -t 200906122350 {} \; 27 | ADD legal legal 28 | ADD migrations migrations 29 | RUN mkdir -p test 30 | ADD test/helpers test/helpers 31 | ADD mocha.js nanoWeb3Provider.js multiWalletProvider.js cmdLinePKProvider.js consolePKProvider.js truffle.js ./ 32 | -------------------------------------------------------------------------------- /ICBM.md: -------------------------------------------------------------------------------- 1 | # Outdated ICBM Information 2 | 3 | ### Prefill Agreements 4 | 5 | Run 6 | 7 | ``` 8 | yarn prefillAgreements 9 | ``` 10 | 11 | In order to prefill legal Agreements with correct addresses of contracts and roles. The script 12 | automatically fills both `NEUMARK TOKEN HOLDER AGREEMENT` and `RESERVATION AGREEMENT` with correct 13 | addresses for 14 | 15 | - Neumark contract address 16 | - Commitment contract Address 17 | - PLATFORM_OPERATOR_REPRESENTATIVE 18 | 19 | ### Upload files to IPFS 20 | 21 | run 22 | 23 | ``` 24 | yarn uploadAgreements [filePath1,filePath2 ...] 25 | ``` 26 | 27 | In order to upload files to IPFS you can run this script, you must provide an IPFS node address. 28 | This tool will use IPFS api in order to upload files to IPFS You can leave files empty to upload 29 | default files 30 | 31 | Currently default files are 32 | 33 | `./legal/NEUMARK TOKEN HOLDER AGREEMENT.out` 34 | 35 | `./legal/RESERVATION AGREEMENT.out` 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright © 2017 Neufund 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the “Software”), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial 12 | portions of the Software. 13 | 14 | The software is provided “as is”, without warranty of any kind, express or implied, including but 15 | not limited to the warranties of merchantability, fitness for a particular purpose and 16 | noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages 17 | or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in 18 | connection with the software or the use or other dealings in the software. 19 | -------------------------------------------------------------------------------- /bin/solc.4.24: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/bin/solc.4.24 -------------------------------------------------------------------------------- /bin/solc.4.25: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/bin/solc.4.25 -------------------------------------------------------------------------------- /bin/solc.4.26: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/bin/solc.4.26 -------------------------------------------------------------------------------- /cmdLinePKProvider.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | // eslint-disable-next-line 3 | const Accounts = require("web3-eth-accounts"); 4 | const ProviderEngine = require("web3-provider-engine"); 5 | // eslint-disable-next-line 6 | const Web3Subprovider = require("web3-provider-engine/subproviders/web3.js"); 7 | const HookedWalletEthTxSubprovider = require("web3-provider-engine/subproviders/hooked-wallet-ethtx"); 8 | const inherits = require("util").inherits; 9 | const commandLineArgs = require("command-line-args"); 10 | 11 | // https://github.com/ethereumjs/ethereumjs-wallet/blob/master/src/provider-engine.js 12 | // https://github.com/MetaMask/web3-provider-engine/blob/master/subproviders/hooked-wallet.js 13 | inherits(CmdLinePKSubprovider, HookedWalletEthTxSubprovider); 14 | 15 | function CmdLinePKSubprovider(address, privateKey, params) { 16 | const opts = params || {}; 17 | const lcAddress = address.toLowerCase(); 18 | 19 | opts.getAccounts = cb => { 20 | cb(null, [address]); 21 | }; 22 | 23 | opts.getPrivateKey = (a, cb) => { 24 | const lowercasedAddress = a.toLowerCase(); 25 | if (lowercasedAddress !== lcAddress) { 26 | cb(new Error(`Account ${lowercasedAddress} not found`)); 27 | } else { 28 | cb(null, privateKey); 29 | } 30 | }; 31 | 32 | CmdLinePKSubprovider.super_.call(this, opts); 33 | } 34 | 35 | export function cmdLinePKProvider(nodeUrl) { 36 | const web3HttpProvider = new Web3.providers.HttpProvider(nodeUrl); 37 | const engine = new ProviderEngine(); 38 | 39 | const optionDefinitions = [{ name: "pk", type: String }]; 40 | const options = commandLineArgs(optionDefinitions, { partial: true }); 41 | if (!options.pk) { 42 | throw new Error("Private key wasn't provided. Use --pk paremeter"); 43 | } 44 | 45 | const privateKey = Buffer.from(options.pk.substr(2), "hex"); 46 | const accounts = new Accounts(web3HttpProvider); 47 | const address = accounts.privateKeyToAccount(options.pk).address; 48 | // eslint-disable-next-line 49 | console.log(`Recovered address ${address}`); 50 | 51 | engine.addProvider(new CmdLinePKSubprovider(address, privateKey)); 52 | engine.addProvider(new Web3Subprovider(web3HttpProvider)); 53 | engine.start(); 54 | engine.stop(); 55 | 56 | return engine; 57 | } 58 | -------------------------------------------------------------------------------- /consolePKProvider.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | // eslint-disable-next-line 3 | const Accounts = require("web3-eth-accounts"); 4 | const ProviderEngine = require("web3-provider-engine"); 5 | // eslint-disable-next-line 6 | const Web3Subprovider = require("web3-provider-engine/subproviders/web3.js"); 7 | const HookedWalletEthTxSubprovider = require("web3-provider-engine/subproviders/hooked-wallet-ethtx"); 8 | const inherits = require("util").inherits; 9 | const readlineSync = require("readline-sync"); 10 | 11 | // https://github.com/ethereumjs/ethereumjs-wallet/blob/master/src/provider-engine.js 12 | // https://github.com/MetaMask/web3-provider-engine/blob/master/subproviders/hooked-wallet.js 13 | inherits(ConsolePKSubprovider, HookedWalletEthTxSubprovider); 14 | 15 | function ConsolePKSubprovider(address, privateKey, params) { 16 | const opts = params || {}; 17 | const lcAddress = address.toLowerCase(); 18 | 19 | opts.getAccounts = cb => { 20 | cb(null, [address]); 21 | }; 22 | 23 | opts.getPrivateKey = (a, cb) => { 24 | const lowercasedAddress = a.toLowerCase(); 25 | if (lowercasedAddress !== lcAddress) { 26 | cb(new Error(`Account ${lowercasedAddress} not found`)); 27 | } else { 28 | cb(null, privateKey); 29 | } 30 | }; 31 | 32 | ConsolePKSubprovider.super_.call(this, opts); 33 | } 34 | 35 | export function consolePKProvider(nodeUrl) { 36 | const web3HttpProvider = new Web3.providers.HttpProvider(nodeUrl); 37 | const engine = new ProviderEngine(); 38 | 39 | const pk = readlineSync.question("PK: ", { hideEchoBack: true }); 40 | const privateKey = Buffer.from(pk.substr(2), "hex"); 41 | const accounts = new Accounts(web3HttpProvider); 42 | const address = accounts.privateKeyToAccount(pk).address; 43 | // eslint-disable-next-line 44 | console.log(`Recovered address ${address}`); 45 | 46 | engine.addProvider(new ConsolePKSubprovider(address, privateKey)); 47 | engine.addProvider(new Web3Subprovider(web3HttpProvider)); 48 | engine.start(); 49 | engine.stop(); 50 | 51 | return engine; 52 | } 53 | -------------------------------------------------------------------------------- /contracts/AccessControl/IAccessControlled.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IAccessPolicy.sol"; 4 | 5 | 6 | /// @title enables access control in implementing contract 7 | /// @dev see AccessControlled for implementation 8 | contract IAccessControlled { 9 | 10 | //////////////////////// 11 | // Events 12 | //////////////////////// 13 | 14 | /// @dev must log on access policy change 15 | event LogAccessPolicyChanged( 16 | address controller, 17 | IAccessPolicy oldPolicy, 18 | IAccessPolicy newPolicy 19 | ); 20 | 21 | //////////////////////// 22 | // Public functions 23 | //////////////////////// 24 | 25 | /// @dev allows to change access control mechanism for this contract 26 | /// this method must be itself access controlled, see AccessControlled implementation and notice below 27 | /// @notice it is a huge issue for Solidity that modifiers are not part of function signature 28 | /// then interfaces could be used for example to control access semantics 29 | /// @param newPolicy new access policy to controll this contract 30 | /// @param newAccessController address of ROLE_ACCESS_CONTROLLER of new policy that can set access to this contract 31 | function setAccessPolicy(IAccessPolicy newPolicy, address newAccessController) 32 | public; 33 | 34 | function accessPolicy() 35 | public 36 | constant 37 | returns (IAccessPolicy); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /contracts/AccessControl/IAccessPolicy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title provides subject to role checking logic 5 | contract IAccessPolicy { 6 | 7 | //////////////////////// 8 | // Public functions 9 | //////////////////////// 10 | 11 | /// @notice We don't make this function constant to allow for state-updating access controls such as rate limiting. 12 | /// @dev checks if subject belongs to requested role for particular object 13 | /// @param subject address to be checked against role, typically msg.sender 14 | /// @param role identifier of required role 15 | /// @param object contract instance context for role checking, typically contract requesting the check 16 | /// @param verb additional data, in current AccessControll implementation msg.sig 17 | /// @return if subject belongs to a role 18 | function allowed( 19 | address subject, 20 | bytes32 role, 21 | address object, 22 | bytes4 verb 23 | ) 24 | public 25 | returns (bool); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/AccessControl/StandardRoles.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract StandardRoles { 5 | 6 | //////////////////////// 7 | // Constants 8 | //////////////////////// 9 | 10 | // @notice Soldity somehow doesn't evaluate this compile time 11 | // @dev role which has rights to change permissions and set new policy in contract, keccak256("AccessController") 12 | bytes32 internal constant ROLE_ACCESS_CONTROLLER = 0xac42f8beb17975ed062dcb80c63e6d203ef1c2c335ced149dc5664cc671cb7da; 13 | } 14 | -------------------------------------------------------------------------------- /contracts/Company/ControllerGovernanceToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./ControllerGovernanceEngine.sol"; 4 | import "./IControllerGovernanceToken.sol"; 5 | 6 | 7 | contract ControllerGovernanceToken is 8 | ControllerGovernanceEngine, 9 | IControllerGovernanceToken 10 | { 11 | //////////////////////// 12 | // Constructor 13 | //////////////////////// 14 | 15 | constructor () internal {} 16 | 17 | // 18 | // Implements IControllerEquityToken 19 | // 20 | 21 | function governanceToken() 22 | public 23 | constant 24 | returns ( 25 | IControlledToken token, 26 | Gov.TokenType tokenType, 27 | Gov.TokenState tokenState, 28 | ITokenholderRights holderRights, 29 | bool tokenTransferable 30 | ) 31 | { 32 | return (_t._token, _t._type, _t._state, _t._tokenholderRights, _t._transferable); 33 | } 34 | 35 | // 36 | // Migration storage access 37 | // 38 | 39 | function migrateToken( 40 | IControlledToken token, 41 | Gov.TokenType tokenType, 42 | Gov.TokenState state, 43 | ITokenholderRights rights, 44 | bool transfersEnabled 45 | ) 46 | public 47 | onlyState(Gov.State.Setup) 48 | only(ROLE_COMPANY_UPGRADE_ADMIN) 49 | { 50 | Gov.setToken(_t, token, tokenType, state, rights, transfersEnabled); 51 | } 52 | 53 | //////////////////////// 54 | // Internal Methods 55 | //////////////////////// 56 | 57 | function enableTransfers(bytes32 resolutionId, bool transfersEnabled) 58 | internal 59 | { 60 | if (_t._transferable != transfersEnabled) { 61 | _t._transferable = transfersEnabled; 62 | } 63 | emit LogTransfersStateChanged(resolutionId, _t._token, transfersEnabled); 64 | } 65 | 66 | // 67 | // Observes MGovernanceObserver 68 | // 69 | 70 | function mAfterShareCapitalChange(uint256 newShareCapital) 71 | internal 72 | { 73 | // update total voting power of the equity token 74 | if (_t._type == Gov.TokenType.Equity) { 75 | Gov.setEquityTokenTotalVotingPower(_t, IEquityToken(_t._token), newShareCapital); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /contracts/Company/EquityTokenMetadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../SnapshotToken/Helpers/TokenMetadata.sol"; 4 | 5 | 6 | contract EquityTokenMetadata is TokenMetadata { 7 | 8 | //////////////////////// 9 | // Immutable state 10 | //////////////////////// 11 | 12 | // ISIN https://www.investopedia.com/terms/i/isin.asp 13 | string private _ISIN; 14 | 15 | //////////////////////// 16 | // Constructor 17 | //////////////////////// 18 | 19 | constructor( 20 | string tokenName, 21 | uint8 decimalUnits, 22 | string tokenSymbol, 23 | string version, 24 | string isin 25 | ) 26 | public 27 | TokenMetadata(tokenName, decimalUnits, tokenSymbol, version) 28 | { 29 | _ISIN = isin; 30 | } 31 | 32 | //////////////////////// 33 | // Public functions 34 | //////////////////////// 35 | 36 | function ISIN() public constant returns (string) { 37 | return _ISIN; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/Company/Extras/ESOP/ESOPTypes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract ESOPTypes { 5 | 6 | //////////////////////// 7 | // Types 8 | //////////////////////// 9 | 10 | // enums are numbered starting from 0. NotSet is used to check for non existing mapping 11 | enum EmployeeState { 12 | NotSet, 13 | WaitingForSignature, 14 | Employed, 15 | Terminated, 16 | OptionsExercised 17 | } 18 | 19 | // please note that 32 bit unsigned int is used to represent UNIX time which is enough to represent dates until Sun, 07 Feb 2106 06:28:15 GMT 20 | // storage access is optimized so struct layout is important 21 | // please note that options are indivisible and not transferable 22 | struct Employee { 23 | // when vesting starts 24 | uint32 issueDate; 25 | // wait for employee signature until that time 26 | uint32 timeToSign; 27 | // date when employee was terminated, 0 for not terminated 28 | uint32 terminatedAt; 29 | // when fade out starts, 0 for not set, initally == terminatedAt 30 | // used only when calculating options returned to pool 31 | uint32 fadeoutStarts; 32 | // time at which employee got suspended, 0 - not suspended 33 | uint32 suspendedAt; 34 | // what is employee current status, takes 8 bit in storage 35 | EmployeeState state; 36 | // index in iterable mapping 37 | uint16 idx; 38 | // poolOptions employee gets (exit bonus not included) 39 | uint96 poolOptions; 40 | // extra options employee gets (neufund will not this option) 41 | uint96 extraOptions; 42 | // options exercised if conversion contract allows for partial conversion 43 | uint96 exercisedOptions; 44 | // were bonus options triggered when user converted 45 | bool acceleratedVestingBonusTriggered; 46 | // still free 47 | // 39 bits 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/Company/Extras/ESOP/IESOPOptionsConverter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | // intended to be implemented by equity token controller that provides ESOP 5 | contract IESOPOptionsConverter { 6 | /// exercise of options for given employee and amount 7 | /// @param employee on which address to perform conversion, mind that it could be legal rep address in case company is doing the conversion for employee that didn't show up 8 | /// @param poolOptions how many options from pooled options to convert 9 | /// @param extraOptions as above, for extra options 10 | /// @param bonusOptions as above, for bonus options, if > 0 it means that user agreed to accelerated vesting conditions 11 | /// @param exercisedOptions all options already exercised by employee 12 | /// @param optionsPerShareCapitalUnit how many options per share capital unit - so token conversion may be scaled 13 | /// @return number of options actually converted. in case of final conversion must be all exercised options 14 | function exerciseOptions( 15 | address employee, 16 | uint256 poolOptions, 17 | uint256 extraOptions, 18 | uint256 bonusOptions, 19 | uint256 exercisedOptions, 20 | uint256 optionsPerShareCapitalUnit) 21 | public 22 | returns(uint256 convertedOptions); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/Company/Extras/RegDTransferController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../SingleEquityTokenController.sol"; 4 | 5 | 6 | contract RegDTransferController is 7 | SingleEquityTokenController 8 | { 9 | //////////////////////// 10 | // Constructor 11 | //////////////////////// 12 | 13 | constructor( 14 | Universe universe, 15 | address companyLegalRep 16 | ) 17 | public 18 | SingleEquityTokenController(universe, companyLegalRep) 19 | {} 20 | 21 | // 22 | // Implements ITokenController 23 | // 24 | 25 | function onTransfer(address broker, address from, address to, uint256 amount) 26 | public 27 | constant 28 | returns (bool allow) 29 | { 30 | // ask base controller if transfers are enables 31 | allow = SingleEquityTokenController.onTransfer(broker, from, to, amount); 32 | // control for reg d lock in in funded state 33 | if (allow && _g._state == Gov.State.Funded) { 34 | IIdentityRegistry registry = IIdentityRegistry(_g.UNIVERSE.identityRegistry()); 35 | IdentityRecord.IdentityClaims memory claims = IdentityRecord.deserializeClaims(registry.getClaims(from)); 36 | // perform additional checks for token holders under reg-d regulations 37 | if (claims.requiresRegDAccreditation) { 38 | // deny transfer if in lockdown period is in place 39 | // first take a date at which ETO was successfully completed 40 | IETOCommitment commitment = IETOCommitment(_offerings[0]); 41 | // allow transfer if 1 year passed form the date tokens could be claimed 42 | allow = block.timestamp > commitment.startOf(ETOState.Claim) + 365 days; 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /contracts/Company/IControlledToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IAgreement.sol"; 4 | import "../Standards/IERC677Token.sol"; 5 | import "../Standards/IERC223Token.sol"; 6 | import "../Standards/IClonedTokenParent.sol"; 7 | import "./IEquityTokenController.sol"; 8 | import "../Standards/ITokenControllerHook.sol"; 9 | 10 | 11 | // minimum set of interfaces required by governance engine to control a token 12 | // - must be snapshotable 13 | // - must support ERC20 interface 14 | // - must support ERC223 transfer 15 | // - must support hook for standard token controller 16 | contract IControlledToken is 17 | IClonedTokenParent, 18 | IERC223Token, 19 | ITokenControllerHook 20 | {} 21 | -------------------------------------------------------------------------------- /contracts/Company/IControllerDividends.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IERC223Token.sol"; 4 | import "../Standards/IERC223Callback.sol"; 5 | 6 | 7 | /// @title interface of governance module providing payouts from payment tokens against pro rata token 8 | /// @dev actual payout happens via ERC223 transfer and IERC223Callback implementation 9 | contract IControllerDividends is IERC223Callback { 10 | 11 | //////////////////////// 12 | // Governance Module Id 13 | //////////////////////// 14 | 15 | bytes32 internal constant ControllerDividendsId = 0x6f34e3bc451d7c62ae86b2e212b7cb207815b826f8de016c0128b0d3762753ae; 16 | uint256 internal constant ControllerDividendsV = 0; 17 | 18 | //////////////////////// 19 | // Interface Methods 20 | //////////////////////// 21 | 22 | // declare amount of paymentToken to be paid against governance token, does not need shareholder resolution 23 | // resolution is completed via ERC223 transfer of required amount 24 | function ordinaryPayoutResolution( 25 | bytes32 resolutionId, 26 | IERC223Token paymentToken, 27 | uint256 amount, 28 | uint256 recycleAfter, 29 | string resolutionDocumentUrl 30 | ) 31 | public; 32 | 33 | // declare amount of paymentToken to be paid against governance token, requires shareholder resolution 34 | // resolution is completed via ERC223 transfer of required amount 35 | function extraOrdinaryPayoutResolution( 36 | bytes32 resolutionId, 37 | IERC223Token paymentToken, 38 | uint256 amount, 39 | uint256 recycleAfter, 40 | string resolutionDocumentUrl 41 | ) 42 | public; 43 | } 44 | -------------------------------------------------------------------------------- /contracts/Company/IControllerETO.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../ETO/IETOCommitment.sol"; 4 | 5 | 6 | /// @title interface of governance module providing methods to start and carry on token offering 7 | contract IControllerETO is IETOCommitmentObserver { 8 | 9 | //////////////////////// 10 | // Governance Module Id 11 | //////////////////////// 12 | 13 | bytes32 internal constant ControllerETOId = 0x1c7166c78ec7465184d422ad6e22121b4881a63128a89653179065e03625ae87; 14 | uint256 internal constant ControllerETOV = 0; 15 | 16 | //////////////////////// 17 | // Events 18 | //////////////////////// 19 | 20 | // offering of the token in ETO failed (Refund) 21 | event LogOfferingFailed( 22 | address etoCommitment, 23 | address equityToken 24 | ); 25 | 26 | // offering of the token in ETO succeeded (with all on-chain consequences) 27 | event LogOfferingSucceeded( 28 | address etoCommitment, 29 | address equityToken, 30 | uint256 newShares 31 | ); 32 | 33 | // 34 | event LogOfferingRegistered( 35 | bytes32 indexed resolutionId, 36 | address etoCommitment, 37 | address equityToken 38 | ); 39 | 40 | //////////////////////// 41 | // Interface Methods 42 | //////////////////////// 43 | 44 | function tokenOfferings() 45 | public 46 | constant 47 | returns ( 48 | address[] offerings 49 | ); 50 | 51 | // starts new equity token offering 52 | function startNewOffering(bytes32 resolutionId, IETOCommitment commitment) 53 | public; 54 | } 55 | -------------------------------------------------------------------------------- /contracts/Company/IControllerGovernance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./Gov.sol"; 4 | import "./IControllerGovernanceEngine.sol"; 5 | import "./IControllerGeneralInformation.sol"; 6 | import "./IControllerGovernanceToken.sol"; 7 | import "./IControllerETO.sol"; 8 | import "./IEquityTokenController.sol"; 9 | import "./IControllerDividends.sol"; 10 | import "../Standards/IAgreement.sol"; 11 | import "../Standards/IContractId.sol"; 12 | 13 | 14 | /// @title a reference interface that groups all possible governance module interfaces 15 | contract IControllerGovernance is 16 | IAgreement, 17 | IEquityTokenController, 18 | IControllerGovernanceEngine, 19 | IControllerGeneralInformation, 20 | IControllerGovernanceToken, 21 | IControllerETO, 22 | IControllerDividends, 23 | IContractId 24 | { 25 | // this will close company (transition to terminal state) and close all associated tokens 26 | // requires decision to be made before according to implemented governance 27 | // also requires that certain obligations are met like proceeds were distributed 28 | // so anyone should be able to call this function 29 | // function closeCompany() public; 30 | 31 | // this will cancel closing of the company due to obligations not met in time 32 | // being able to cancel closing should not depend on who is calling the function. 33 | // function cancelCompanyClosing() public; 34 | 35 | // list of governance modules in controller, same scheme as IContractId 36 | /// @dev includes contractId as last one 37 | // function moduleId() public pure returns (bytes32[6] ids, uint256[6] versions); 38 | } 39 | -------------------------------------------------------------------------------- /contracts/Company/IControllerGovernanceToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./Gov.sol"; 4 | 5 | 6 | /// @title interface of governance module to manage governance (main) token of the controller 7 | /// @dev interface assumes single governance token that is a default token for voting and proceed distribution 8 | /// governance token is optional, it's possible to setup a controller without any token 9 | contract IControllerGovernanceToken { 10 | 11 | //////////////////////// 12 | // Governance Module Id 13 | //////////////////////// 14 | 15 | bytes32 internal constant ControllerGovernanceTokenId = 0x156c4a2914517b2fdbf2f694bac9d69e03910b75d3298033e1f4f431b517703d; 16 | uint256 internal constant ControllerGovernanceTokenV = 0; 17 | 18 | //////////////////////// 19 | // Events 20 | //////////////////////// 21 | 22 | // logged when transferability of given token was changed 23 | event LogTransfersStateChanged( 24 | bytes32 indexed resolutionId, 25 | address equityToken, 26 | bool transfersEnabled 27 | ); 28 | 29 | //////////////////////// 30 | // Interface methods 31 | //////////////////////// 32 | 33 | function governanceToken() 34 | public 35 | constant 36 | returns ( 37 | IControlledToken token, 38 | Gov.TokenType tokenType, 39 | Gov.TokenState tokenState, 40 | ITokenholderRights holderRights, 41 | bool tokenTransferable 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /contracts/Company/IEquityTokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IAgreement.sol"; 4 | import "../Standards/ITokenController.sol"; 5 | 6 | 7 | contract IEquityTokenController is 8 | IAgreement, 9 | ITokenController 10 | { 11 | /// controls if sender can change old nominee to new nominee 12 | /// @dev for this to succeed typically a voting of the token holders should happen and new nominee should be set 13 | function onChangeNominee(address sender, address oldNominee, address newNominee) 14 | public 15 | constant 16 | returns (bool); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/Company/ITokenholderRights.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract ITokenholderRights { 5 | 6 | //////////////////////// 7 | // Constants 8 | //////////////////////// 9 | 10 | // number of actions declared by Action enum 11 | uint256 internal constant BYLAW_STRUCT_PROPS = 9; 12 | 13 | //////////////////////// 14 | // Interface Methods 15 | //////////////////////// 16 | 17 | // get bylaw for specific action 18 | function getBylaw(uint8 action) 19 | public 20 | constant 21 | returns (uint56); 22 | 23 | // decodes uint56 packed bylaw into uint256 array that can be casted from ActionBylaw 24 | function decodeBylaw(uint56 encodedBylaw) 25 | public 26 | pure 27 | returns (uint256[BYLAW_STRUCT_PROPS] memory decodedBylaw); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/Company/MGovernanceObserver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | /// @title self observing interface for controller governance 4 | /// @dev observed by final contract to bind various modules together 5 | contract MGovernanceObserver { 6 | 7 | /// @notice called whenever share capital changes 8 | /// @dev called after state change is done 9 | function mAfterShareCapitalChange(uint256 newShareCapital) 10 | internal; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /contracts/Company/ShareholderRights.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | // represents a set of rights that shareholder ("nominee" in case of equity token with nominee structure) has 5 | // those rights are fully/partially passed to the token holders, see EquityTokenholderRights 6 | contract ShareholderRights { 7 | 8 | //////////////////////// 9 | // Immutable state 10 | //////////////////////// 11 | 12 | // a right to drag along (or be dragged) on exit 13 | bool public constant HAS_DRAG_ALONG_RIGHTS = true; 14 | // a right to tag along 15 | bool public constant HAS_TAG_ALONG_RIGHTS = true; 16 | // access to company information 17 | bool public constant HAS_GENERAL_INFORMATION_RIGHTS = true; 18 | // rights to receive dividends and other proceedings 19 | bool public constant HAS_ECONOMIC_RIGHTS = true; 20 | // has voting rights 21 | bool public HAS_VOTING_RIGHTS; 22 | // liquidation preference multiplicator as decimal fraction 23 | uint256 public LIQUIDATION_PREFERENCE_MULTIPLIER_FRAC; 24 | // founder's vesting 25 | bool public HAS_FOUNDERS_VESTING; 26 | 27 | //////////////////////// 28 | // Constructor 29 | //////////////////////// 30 | 31 | constructor( 32 | bool hasVotingRights, 33 | uint256 liquidationPreferenceMultiplierFrac, 34 | bool hasFoundersVesting 35 | ) 36 | internal 37 | { 38 | HAS_VOTING_RIGHTS = hasVotingRights; 39 | LIQUIDATION_PREFERENCE_MULTIPLIER_FRAC = liquidationPreferenceMultiplierFrac; 40 | HAS_FOUNDERS_VESTING = hasFoundersVesting; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/Compat/ERC223LegacyCallbackCompat.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title makes modern ERC223 contracts compatible with the legacy implementation 5 | /// @dev should be used for all receivers of tokens sent by ICBMEtherToken and NEU 6 | contract ERC223LegacyCallbackCompat { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | function onTokenTransfer(address wallet, uint256 amount, bytes data) 13 | public 14 | { 15 | tokenFallback(wallet, amount, data); 16 | } 17 | 18 | function tokenFallback(address wallet, uint256 amount, bytes data) 19 | public; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /contracts/Deprecations/IControllerGovernance_v1_3.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IAgreement.sol"; 4 | import "../Standards/IContractId.sol"; 5 | 6 | 7 | /// @title deprecated version implemented by PlaceholderEquityTokenControler:v0 (FF ETO and Greyp) 8 | /// @dev preserving only properties required for migration 9 | // version history as per contract id (0xf7e00d1a4168be33cbf27d32a37a5bc694b3a839684a8c2bef236e3594345d70) 10 | // 0 - initial version 11 | // 1 - standardizes migration function to require two side commitment 12 | // 2 - migration management shifted from company to UPGRADE ADMIN 13 | // 3 - company shares replaced by share capital 14 | contract IControllerGovernance_v1_3 is 15 | IAgreement, 16 | IContractId 17 | { 18 | 19 | function state() 20 | public 21 | constant 22 | returns (uint256); 23 | 24 | // address of company legal representative able to sign agreements 25 | function companyLegalRepresentative() 26 | public 27 | constant 28 | returns (address); 29 | 30 | // return basic shareholder information 31 | function shareholderInformation() 32 | public 33 | constant 34 | returns ( 35 | // v0-2 returns shares, not share capital 36 | uint256 shareCapital, 37 | uint256 companyValuationEurUlps, 38 | address shareholderRights 39 | ); 40 | 41 | // returns cap table 42 | function capTable() 43 | public 44 | constant 45 | returns ( 46 | address[] equityTokens, 47 | uint256[] shares 48 | ); 49 | 50 | // returns all started offerings 51 | function tokenOfferings() 52 | public 53 | constant 54 | returns ( 55 | address[] offerings, 56 | address[] equityTokens 57 | ); 58 | 59 | // 60 | // Old Migration Interface v1-3 61 | // 62 | 63 | /// @dev requires UPGRADE ADMIN role in v2-3, company in v1 64 | function changeTokenController(address newController) 65 | public; 66 | 67 | function newTokenController() 68 | public 69 | constant 70 | returns (address); 71 | 72 | function oldTokenController() 73 | public 74 | constant 75 | returns (address); 76 | 77 | } 78 | -------------------------------------------------------------------------------- /contracts/Deprecations/README.md: -------------------------------------------------------------------------------- 1 | # Deprecated interfaces 2 | -------------------------------------------------------------------------------- /contracts/Deprecations/deprecations.json: -------------------------------------------------------------------------------- 1 | { 2 | "0x45a709aff6d5ae42cb70f87551d8d7dbec5235cf2baa71a009ed0a9795258d8f": [ 3 | {"0": "IEquityToken_v0"} 4 | ], 5 | "0xf7e00d1a4168be33cbf27d32a37a5bc694b3a839684a8c2bef236e3594345d70": [ 6 | {"3": "IControllerGovernance_v1_3"} 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /contracts/ETO/ETODurationTerms.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IContractId.sol"; 4 | 5 | 6 | /// @title sets duration of states in ETO 7 | contract ETODurationTerms is IContractId { 8 | 9 | //////////////////////// 10 | // Immutable state 11 | //////////////////////// 12 | 13 | // duration of Whitelist state 14 | uint32 public WHITELIST_DURATION; 15 | 16 | // duration of Public state 17 | uint32 public PUBLIC_DURATION; 18 | 19 | // time for Nominee and Company to sign Investment Agreement offchain and present proof on-chain 20 | uint32 public SIGNING_DURATION; 21 | 22 | // time for Claim before fee payout from ETO to NEU holders 23 | uint32 public CLAIM_DURATION; 24 | 25 | //////////////////////// 26 | // Constructor 27 | //////////////////////// 28 | 29 | constructor( 30 | uint32 whitelistDuration, 31 | uint32 publicDuration, 32 | uint32 signingDuration, 33 | uint32 claimDuration 34 | ) 35 | public 36 | { 37 | WHITELIST_DURATION = whitelistDuration; 38 | PUBLIC_DURATION = publicDuration; 39 | SIGNING_DURATION = signingDuration; 40 | CLAIM_DURATION = claimDuration; 41 | } 42 | 43 | // 44 | // Implements IContractId 45 | // 46 | 47 | function contractId() public pure returns (bytes32 id, uint256 version) { 48 | return (0x5fb50201b453799d95f8a80291b940f1c543537b95bff2e3c78c2e36070494c0, 0); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/ETO/IETOCommitmentObserver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IETOCommitmentStates.sol"; 4 | 5 | 6 | /// @title provides callback on state transitions 7 | /// @dev observer called after the state() of commitment contract was set 8 | contract IETOCommitmentObserver is IETOCommitmentStates { 9 | function onStateTransition(ETOState oldState, ETOState newState) public; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/ETO/IETOCommitmentStates.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title state space of ETOCommitment 5 | contract IETOCommitmentStates { 6 | //////////////////////// 7 | // Types 8 | //////////////////////// 9 | 10 | // order must reflect time precedence, do not change order below 11 | enum ETOState { 12 | Setup, // Initial state 13 | Whitelist, 14 | Public, 15 | Signing, 16 | Claim, 17 | Payout, // Terminal state 18 | Refund // Terminal state 19 | } 20 | 21 | // number of states in enum 22 | uint256 constant internal ETO_STATES_COUNT = 7; 23 | } 24 | -------------------------------------------------------------------------------- /contracts/ETO/METOStateMachineObserver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IETOCommitmentStates.sol"; 4 | 5 | 6 | contract METOStateMachineObserver is IETOCommitmentStates { 7 | /// @notice called before state transitions, allows override transition due to additional business logic 8 | /// @dev advance due to time implemented in advanceTimedState, here implement other conditions like 9 | /// max cap reached -> we go to signing 10 | function mBeforeStateTransition(ETOState oldState, ETOState newState) 11 | internal 12 | constant 13 | returns (ETOState newStateOverride); 14 | 15 | /// @notice gets called after every state transition. 16 | function mAfterTransition(ETOState oldState, ETOState newState) 17 | internal; 18 | 19 | /// @notice gets called after business logic, may induce state transition 20 | function mAdavanceLogicState(ETOState oldState) 21 | internal 22 | constant 23 | returns (ETOState); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/ICBM/ICBMEuroTokenMigrationTarget.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./MigrationTarget.sol"; 4 | 5 | 6 | contract ICBMEuroTokenMigrationTarget is 7 | MigrationTarget 8 | { 9 | //////////////////////// 10 | // Public functions 11 | //////////////////////// 12 | 13 | /// @notice accepts migration of single eur-t token holder 14 | /// @dev allowed to be called only from migration source, do not forget to add accessor modifier `onlyMigrationSource` in implementation 15 | function migrateEuroTokenOwner(address owner, uint256 amount) 16 | public; 17 | } 18 | -------------------------------------------------------------------------------- /contracts/ICBM/ICBMLockedAccountMigration.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./MigrationTarget.sol"; 4 | 5 | 6 | /// @notice implemented in the contract that is the target of LockedAccount migration 7 | /// migration process is removing investors balance from source LockedAccount fully 8 | /// target should re-create investor with the same balance, totalLockedAmount and totalInvestors are invariant during migration 9 | contract ICBMLockedAccountMigration is 10 | MigrationTarget 11 | { 12 | //////////////////////// 13 | // Public functions 14 | //////////////////////// 15 | 16 | // implemented in migration target, apply `onlyMigrationSource()` modifier, modifiers are not inherited 17 | function migrateInvestor( 18 | address investor, 19 | uint256 balance, 20 | uint256 neumarksDue, 21 | uint256 unlockDate 22 | ) 23 | public; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /contracts/ICBM/ICBMRoles.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title standard access roles of the Platform 5 | /// @dev constants are kept in CODE not in STORAGE so they are comparatively cheap 6 | contract ICBMRoles { 7 | 8 | //////////////////////// 9 | // Constants 10 | //////////////////////// 11 | 12 | // NOTE: All roles are set to the keccak256 hash of the 13 | // CamelCased role name, i.e. 14 | // ROLE_LOCKED_ACCOUNT_ADMIN = keccak256("LockedAccountAdmin") 15 | 16 | // may setup LockedAccount, change disbursal mechanism and set migration 17 | bytes32 internal constant ROLE_LOCKED_ACCOUNT_ADMIN = 0x4675da546d2d92c5b86c4f726a9e61010dce91cccc2491ce6019e78b09d2572e; 18 | } 19 | -------------------------------------------------------------------------------- /contracts/ICBM/IMigrationSource.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IMigrationTarget.sol"; 4 | 5 | 6 | /// @notice implemented in the contract that stores state to be migrated 7 | /// @notice contract is called migration source 8 | /// @dev migration target implements IMigrationTarget interface, when it is passed in 'enableMigration' function 9 | /// @dev 'migrate' function may be called to migrate part of state owned by msg.sender 10 | /// @dev in legal terms this corresponds to amending/changing agreement terms by co-signature of parties 11 | contract IMigrationSource { 12 | 13 | //////////////////////// 14 | // Events 15 | //////////////////////// 16 | 17 | event LogMigrationEnabled( 18 | address target 19 | ); 20 | 21 | //////////////////////// 22 | // Public functions 23 | //////////////////////// 24 | 25 | /// @notice should migrate state owned by msg.sender 26 | /// @dev intended flow is to: read source state, clear source state, call migrate function on target, log success event 27 | function migrate() 28 | public; 29 | 30 | /// @notice should enable migration to migration target 31 | /// @dev should limit access to specific role in implementation 32 | function enableMigration(IMigrationTarget migration) 33 | public; 34 | 35 | /// @notice returns current migration target 36 | function currentMigrationTarget() 37 | public 38 | constant 39 | returns (IMigrationTarget); 40 | } 41 | -------------------------------------------------------------------------------- /contracts/ICBM/IMigrationTarget.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @notice implemented in the contract that is the target of state migration 5 | /// @dev implementation must provide actual function that will be called by source to migrate state 6 | contract IMigrationTarget { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | // should return migration source address 13 | function currentMigrationSource() 14 | public 15 | constant 16 | returns (address); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/ICBM/MigrationTarget.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IMigrationTarget.sol"; 4 | 5 | 6 | /// @notice mixin that enables contract to receive migration 7 | /// @dev when derived from 8 | contract MigrationTarget is 9 | IMigrationTarget 10 | { 11 | //////////////////////// 12 | // Modifiers 13 | //////////////////////// 14 | 15 | // intended to be applied on migration receiving function 16 | modifier onlyMigrationSource() { 17 | require(msg.sender == currentMigrationSource(), "NF_INV_SOURCE"); 18 | _; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/ICBM/TimeSource.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract TimeSource { 5 | 6 | //////////////////////// 7 | // Internal functions 8 | //////////////////////// 9 | 10 | function currentTime() internal constant returns (uint256) { 11 | return block.timestamp; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/IsContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IsContract { 5 | 6 | //////////////////////// 7 | // Internal functions 8 | //////////////////////// 9 | 10 | function isContract(address addr) 11 | internal 12 | constant 13 | returns (bool) 14 | { 15 | uint256 size; 16 | // takes 700 gas 17 | assembly { size := extcodesize(addr) } 18 | return size > 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/KnownContracts.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title known contracts of the platform 5 | /// should be returned by contractId() method of IContradId.sol. caluclated like so: keccak256("neufund-platform:Neumark") 6 | /// @dev constants are kept in CODE not in STORAGE so they are comparatively cheap 7 | contract KnownContracts { 8 | 9 | //////////////////////// 10 | // Constants 11 | //////////////////////// 12 | 13 | // keccak256("neufund-platform:FeeDisbursalController") 14 | bytes32 internal constant FEE_DISBURSAL_CONTROLLER = 0xfc72936b568fd5fc632b76e8feac0b717b4db1fce26a1b3b623b7fb6149bd8ae; 15 | 16 | // keccak256("neufund-platform:IVotingController") 17 | bytes32 internal constant VOTING_CONTROLLER = 0xce4f452ebfdf0ed551c9b34a50b64c79ac0e36168a6215a232de447013515ac6; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /contracts/Reclaimable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./Standards/IBasicToken.sol"; 4 | import "./AccessControl/AccessControlled.sol"; 5 | import "./AccessRoles.sol"; 6 | 7 | 8 | /// @title allows deriving contract to recover any token or ether that it has balance of 9 | /// @notice note that this opens your contracts to claims from various people saying they lost tokens and they want them back 10 | /// be ready to handle such claims 11 | /// @dev use with care! 12 | /// 1. ROLE_RECLAIMER is allowed to claim tokens, it's not returning tokens to original owner 13 | /// 2. in derived contract that holds any token by design you must override `reclaim` and block such possibility. 14 | /// see ICBMLockedAccount as an example 15 | contract Reclaimable is AccessControlled, AccessRoles { 16 | 17 | //////////////////////// 18 | // Constants 19 | //////////////////////// 20 | 21 | IBasicToken constant internal RECLAIM_ETHER = IBasicToken(0x0); 22 | 23 | //////////////////////// 24 | // Public functions 25 | //////////////////////// 26 | 27 | function reclaim(IBasicToken token) 28 | public 29 | only(ROLE_RECLAIMER) 30 | { 31 | address reclaimer = msg.sender; 32 | if(token == RECLAIM_ETHER) { 33 | reclaimer.transfer(address(this).balance); 34 | } else { 35 | uint256 balance = token.balanceOf(this); 36 | require(token.transfer(reclaimer, balance)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/Serialization.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title serialization of basic types from/to bytes 5 | library Serialization { 6 | 7 | //////////////////////// 8 | // Internal functions 9 | //////////////////////// 10 | function decodeAddress(bytes b) 11 | internal 12 | pure 13 | returns (address a) 14 | { 15 | require(b.length == 20); 16 | assembly { 17 | // load memory area that is address "carved out" of 64 byte bytes. prefix is zeroed 18 | a := and(mload(add(b, 20)), 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) 19 | } 20 | } 21 | 22 | function decodeAddressUInt256(bytes b) 23 | internal 24 | pure 25 | returns (address a, uint256 i) 26 | { 27 | require(b.length == 52); 28 | assembly { 29 | // load memory area that is address "carved out" of 64 byte bytes. prefix is zeroed 30 | a := and(mload(add(b, 20)), 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) 31 | i := mload(add(b, 52)) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/Snapshot/Daily.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./MSnapshotPolicy.sol"; 4 | 5 | 6 | /// @title creates new snapshot id on each day boundary 7 | /// @dev snapshot id is unix timestamp of current day boundary 8 | contract Daily is MSnapshotPolicy { 9 | 10 | //////////////////////// 11 | // Constants 12 | //////////////////////// 13 | 14 | // Floor[2**128 / 1 days] 15 | uint256 private MAX_TIMESTAMP = 3938453320844195178974243141571391; 16 | 17 | //////////////////////// 18 | // Constructor 19 | //////////////////////// 20 | 21 | /// @param start snapshotId from which to start generating values, used to prevent cloning from incompatible schemes 22 | /// @dev start must be for the same day or 0, required for token cloning 23 | constructor(uint256 start) internal { 24 | // 0 is invalid value as we are past unix epoch 25 | if (start > 0) { 26 | uint256 base = dayBase(uint128(block.timestamp)); 27 | // must be within current day base 28 | require(start >= base); 29 | // dayBase + 2**128 will not overflow as it is based on block.timestamp 30 | require(start < base + 2**128); 31 | } 32 | } 33 | 34 | //////////////////////// 35 | // Public functions 36 | //////////////////////// 37 | 38 | function snapshotAt(uint256 timestamp) 39 | public 40 | constant 41 | returns (uint256) 42 | { 43 | require(timestamp < MAX_TIMESTAMP); 44 | 45 | return dayBase(uint128(timestamp)); 46 | } 47 | 48 | //////////////////////// 49 | // Internal functions 50 | //////////////////////// 51 | 52 | // 53 | // Implements MSnapshotPolicy 54 | // 55 | 56 | function mAdvanceSnapshotId() 57 | internal 58 | returns (uint256) 59 | { 60 | return mCurrentSnapshotId(); 61 | } 62 | 63 | function mCurrentSnapshotId() 64 | internal 65 | constant 66 | returns (uint256) 67 | { 68 | // disregard overflows on block.timestamp, see MAX_TIMESTAMP 69 | return dayBase(uint128(block.timestamp)); 70 | } 71 | 72 | function dayBase(uint128 timestamp) 73 | internal 74 | pure 75 | returns (uint256) 76 | { 77 | // Round down to the start of the day (00:00 UTC) and place in higher 128bits 78 | return 2**128 * (uint256(timestamp) / 1 days); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /contracts/Snapshot/Extras/EveryBlock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../MSnapshotPolicy.sol"; 4 | 5 | 6 | /// @title creates snapshot id on each block 7 | /// @dev this is snapshotting mode of MineMe token 8 | contract EveryBlock is MSnapshotPolicy { 9 | 10 | //////////////////////// 11 | // Internal functions 12 | //////////////////////// 13 | 14 | // 15 | // Implements MSnapshotPolicy 16 | // 17 | 18 | function mAdvanceSnapshotId() 19 | internal 20 | returns (uint256) 21 | { 22 | return block.number; 23 | } 24 | 25 | function mCurrentSnapshotId() 26 | internal 27 | constant 28 | returns (uint256) 29 | { 30 | return block.number; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/Snapshot/Extras/Snapshotable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Standards/ISnapshotable.sol"; 4 | import "../MSnapshotPolicy.sol"; 5 | 6 | 7 | /// @title creates snapshot as requested via ISnapshotable interface 8 | contract Snapshotable is 9 | MSnapshotPolicy, 10 | ISnapshotable 11 | { 12 | //////////////////////// 13 | // Mutable state 14 | //////////////////////// 15 | 16 | uint256 private _currentSnapshotId; 17 | 18 | //////////////////////// 19 | // Constructor 20 | //////////////////////// 21 | 22 | constructor(uint256 start) 23 | internal 24 | { 25 | _currentSnapshotId = start; 26 | } 27 | 28 | //////////////////////// 29 | // Public functions 30 | //////////////////////// 31 | 32 | function createSnapshot() 33 | public 34 | returns (uint256) 35 | { 36 | require(_currentSnapshotId < 2**256 - 1); 37 | 38 | // Increment the snapshot counter 39 | _currentSnapshotId += 1; 40 | 41 | // Log and return 42 | emit LogSnapshotCreated(_currentSnapshotId); 43 | return _currentSnapshotId; 44 | } 45 | 46 | function currentSnapshotId() 47 | public 48 | constant 49 | returns (uint256) 50 | { 51 | return mCurrentSnapshotId(); 52 | } 53 | 54 | //////////////////////// 55 | // Internal functions 56 | //////////////////////// 57 | 58 | function mAdvanceSnapshotId() 59 | internal 60 | returns (uint256) 61 | { 62 | return _currentSnapshotId; 63 | } 64 | 65 | function mCurrentSnapshotId() 66 | internal 67 | constant 68 | returns (uint256) 69 | { 70 | return _currentSnapshotId; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /contracts/Snapshot/MSnapshotPolicy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title Abstracts snapshot id creation logics 5 | /// @dev Mixin (internal interface) of the snapshot policy which abstracts snapshot id creation logics from Snapshot contract 6 | /// @dev to be implemented and such implementation should be mixed with Snapshot-derived contract, see EveryBlock for simplest example of implementation and StandardSnapshotToken 7 | contract MSnapshotPolicy { 8 | 9 | //////////////////////// 10 | // Internal functions 11 | //////////////////////// 12 | 13 | // The snapshot Ids need to be strictly increasing. 14 | // Whenever the snaspshot id changes, a new snapshot will be created. 15 | // As long as the same snapshot id is being returned, last snapshot will be updated as this indicates that snapshot id didn't change 16 | // 17 | // Values passed to `hasValueAt` and `valuteAt` are required 18 | // to be less or equal to `mCurrentSnapshotId()`. 19 | function mAdvanceSnapshotId() 20 | internal 21 | returns (uint256); 22 | 23 | // this is a version of mAdvanceSnapshotId that does not modify state but MUST return the same value 24 | // it is required to implement ITokenSnapshots interface cleanly 25 | function mCurrentSnapshotId() 26 | internal 27 | constant 28 | returns (uint256); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/BasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | import "../Standards/IBasicToken.sol"; 5 | import "../Math.sol"; 6 | import "./Helpers/MTokenTransferController.sol"; 7 | import "./Helpers/MTokenTransfer.sol"; 8 | 9 | 10 | /** 11 | * @title Basic token 12 | * @dev Basic version of StandardToken, with no allowances. 13 | */ 14 | contract BasicToken is 15 | MTokenTransfer, 16 | MTokenTransferController, 17 | IBasicToken 18 | { 19 | 20 | //////////////////////// 21 | // Mutable state 22 | //////////////////////// 23 | 24 | mapping(address => uint256) internal _balances; 25 | 26 | uint256 internal _totalSupply; 27 | 28 | //////////////////////// 29 | // Public functions 30 | //////////////////////// 31 | 32 | /** 33 | * @dev transfer token for a specified address 34 | * @param to The address to transfer to. 35 | * @param amount The amount to be transferred. 36 | */ 37 | function transfer(address to, uint256 amount) 38 | public 39 | returns (bool) 40 | { 41 | mTransfer(msg.sender, to, amount); 42 | return true; 43 | } 44 | 45 | /// @dev This function makes it easy to get the total number of tokens 46 | /// @return The total number of tokens 47 | function totalSupply() 48 | public 49 | constant 50 | returns (uint256) 51 | { 52 | return _totalSupply; 53 | } 54 | 55 | /** 56 | * @dev Gets the balance of the specified address. 57 | * @param owner The address to query the the balance of. 58 | * @return An uint256 representing the amount owned by the passed address. 59 | */ 60 | function balanceOf(address owner) 61 | public 62 | constant 63 | returns (uint256 balance) 64 | { 65 | return _balances[owner]; 66 | } 67 | 68 | //////////////////////// 69 | // Internal functions 70 | //////////////////////// 71 | 72 | // 73 | // Implements MTokenTransfer 74 | // 75 | 76 | function mTransfer(address from, address to, uint256 amount) 77 | internal 78 | { 79 | require(to != address(0)); 80 | require(mOnTransfer(from, to, amount)); 81 | 82 | _balances[from] = Math.sub(_balances[from], amount); 83 | _balances[to] = Math.add(_balances[to], amount); 84 | emit Transfer(from, to, amount); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Extensions/ISnapshotableToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Standards/IBasicToken.sol"; 4 | import "../../Standards/ISnapshotable.sol"; 5 | import "../../Standards/ITokenSnapshots.sol"; 6 | 7 | 8 | contract ISnapshotableToken is ISnapshotable, ITokenSnapshots, IBasicToken { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Extensions/Vote.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./ISnapshotableToken.sol"; 4 | 5 | 6 | // https://en.wikipedia.org/wiki/Comparison_of_electoral_systems 7 | // 8 | // https://en.wikipedia.org/wiki/Arrow%27s_impossibility_theorem 9 | // https://en.wikipedia.org/wiki/Gibbard%E2%80%93Satterthwaite_theorem 10 | // 11 | // * Votes are public 12 | // * Voting is weighed by amount of tokens owned 13 | // * Votes can be changed 14 | // * 15 | // 16 | // Cardinal systems are a natural fit for a token based voting system. 17 | // * https://en.wikipedia.org/wiki/Approval_voting 18 | // * https://en.wikipedia.org/wiki/Majority_judgment 19 | // → https://en.wikipedia.org/wiki/Range_voting 20 | // 21 | // TODO: Implement Range voting with: 22 | // * Votes proportional to shares (i.e. one vote per share) 23 | // * Proxy voting: ability to delegate voting power 24 | // * Ability to trade voting power (is this the same as above?) 25 | // 26 | // TODO: 27 | contract Vote { 28 | 29 | //////////////////////// 30 | // Immutable state 31 | //////////////////////// 32 | 33 | ISnapshotableToken private TOKEN; 34 | 35 | uint256 private SNAPSHOT; 36 | 37 | bytes32[] private CHOICE_HASHES; 38 | 39 | //////////////////////// 40 | // Mutable state 41 | //////////////////////// 42 | 43 | string[] private _choices; 44 | 45 | uint256[] private _totals; 46 | 47 | //////////////////////// 48 | // Constructor 49 | //////////////////////// 50 | 51 | // Note: we use hashes because Solidity currently does not support passing 52 | // string[] as an argument for external functions. 53 | constructor( 54 | ISnapshotableToken token, 55 | bytes32[] choiceHashes 56 | ) 57 | public 58 | { 59 | TOKEN = token; 60 | SNAPSHOT = token.createSnapshot(); 61 | CHOICE_HASHES = choiceHashes; 62 | _choices.length = CHOICE_HASHES.length; 63 | } 64 | 65 | //////////////////////// 66 | // Public functions 67 | //////////////////////// 68 | 69 | function initChoice(uint256 index, string choice) 70 | public { 71 | require(index < CHOICE_HASHES.length); 72 | require(keccak256(abi.encodePacked(choice)) == CHOICE_HASHES[index]); 73 | _choices[index] = choice; 74 | } 75 | 76 | function vote( 77 | uint256[] // votes 78 | ) 79 | public; 80 | } 81 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/MTokenAllowanceController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title controls spending approvals 5 | /// @dev TokenAllowance observes this interface, Neumark contract implements it 6 | contract MTokenAllowanceController { 7 | 8 | //////////////////////// 9 | // Internal functions 10 | //////////////////////// 11 | 12 | /// @notice Notifies the controller about an approval allowing the 13 | /// controller to react if desired 14 | /// @param owner The address that calls `approve()` 15 | /// @param spender The spender in the `approve()` call 16 | /// @param amount The amount in the `approve()` call 17 | /// @return False if the controller does not authorize the approval 18 | function mOnApprove( 19 | address owner, 20 | address spender, 21 | uint256 amount 22 | ) 23 | internal 24 | returns (bool allow); 25 | 26 | /// @notice Allows to override allowance approved by the owner 27 | /// Primary role is to enable forced transfers, do not override if you do not like it 28 | /// Following behavior is expected in the observer 29 | /// approve() - should revert if mAllowanceOverride() > 0 30 | /// allowance() - should return mAllowanceOverride() if set 31 | /// transferFrom() - should override allowance if mAllowanceOverride() > 0 32 | /// @param owner An address giving allowance to spender 33 | /// @param spender An address getting a right to transfer allowance amount from the owner 34 | /// @return current allowance amount 35 | function mAllowanceOverride( 36 | address owner, 37 | address spender 38 | ) 39 | internal 40 | constant 41 | returns (uint256 allowance); 42 | } 43 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/MTokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./MTokenTransferController.sol"; 4 | import "./MTokenAllowanceController.sol"; 5 | 6 | 7 | /// @title controls approvals and transfers 8 | /// @dev The token controller contract must implement these functions, see Neumark as example 9 | /// @dev please note that controller may be a separate contract that is called from mOnTransfer and mOnApprove functions 10 | contract MTokenController is MTokenTransferController, MTokenAllowanceController { 11 | } 12 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/MTokenMint.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title token generation and destruction 5 | /// @dev internal interface providing token generation and destruction, see MintableSnapshotToken for implementation 6 | contract MTokenMint { 7 | 8 | //////////////////////// 9 | // Internal functions 10 | //////////////////////// 11 | 12 | /// @notice Generates `amount` tokens that are assigned to `owner` 13 | /// @param owner The address that will be assigned the new tokens 14 | /// @param amount The quantity of tokens generated 15 | /// @dev reverts if tokens could not be generated 16 | function mGenerateTokens(address owner, uint256 amount) 17 | internal; 18 | 19 | /// @notice Burns `amount` tokens from `owner` 20 | /// @param owner The address that will lose the tokens 21 | /// @param amount The quantity of tokens to burn 22 | /// @dev reverts if tokens could not be destroyed 23 | function mDestroyTokens(address owner, uint256 amount) 24 | internal; 25 | } 26 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/MTokenTransfer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title internal token transfer function 5 | /// @dev see BasicSnapshotToken for implementation 6 | contract MTokenTransfer { 7 | 8 | //////////////////////// 9 | // Internal functions 10 | //////////////////////// 11 | 12 | /// @dev This is the actual transfer function in the token contract, it can 13 | /// only be called by other functions in this contract. 14 | /// @param from The address holding the tokens being transferred 15 | /// @param to The address of the recipient 16 | /// @param amount The amount of tokens to be transferred 17 | /// @dev reverts if transfer was not successful 18 | function mTransfer( 19 | address from, 20 | address to, 21 | uint256 amount 22 | ) 23 | internal; 24 | } 25 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/MTokenTransferController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title controls token transfers 5 | /// @dev BasicSnapshotToken observes this interface, Neumark contract implements it 6 | contract MTokenTransferController { 7 | 8 | //////////////////////// 9 | // Internal functions 10 | //////////////////////// 11 | 12 | /// @notice Notifies the controller about a token transfer allowing the 13 | /// controller to react if desired 14 | /// @param from The origin of the transfer 15 | /// @param to The destination of the transfer 16 | /// @param amount The amount of the transfer 17 | /// @return False if the controller does not authorize the transfer 18 | function mOnTransfer( 19 | address from, 20 | address to, 21 | uint256 amount 22 | ) 23 | internal 24 | returns (bool allow); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/TokenMetadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Standards/ITokenMetadata.sol"; 4 | 5 | 6 | /// @title adds token metadata to token contract 7 | /// @dev see Neumark for example implementation 8 | contract TokenMetadata is ITokenMetadata { 9 | 10 | //////////////////////// 11 | // Immutable state 12 | //////////////////////// 13 | 14 | // The Token's name: e.g. DigixDAO Tokens 15 | string private NAME; 16 | 17 | // An identifier: e.g. REP 18 | string private SYMBOL; 19 | 20 | // Number of decimals of the smallest unit 21 | uint8 private DECIMALS; 22 | 23 | // An arbitrary versioning scheme 24 | string private VERSION; 25 | 26 | //////////////////////// 27 | // Constructor 28 | //////////////////////// 29 | 30 | /// @notice Constructor to set metadata 31 | /// @param tokenName Name of the new token 32 | /// @param decimalUnits Number of decimals of the new token 33 | /// @param tokenSymbol Token Symbol for the new token 34 | /// @param version Token version ie. when cloning is used 35 | constructor( 36 | string tokenName, 37 | uint8 decimalUnits, 38 | string tokenSymbol, 39 | string version 40 | ) 41 | public 42 | { 43 | NAME = tokenName; // Set the name 44 | SYMBOL = tokenSymbol; // Set the symbol 45 | DECIMALS = decimalUnits; // Set the decimals 46 | VERSION = version; 47 | } 48 | 49 | //////////////////////// 50 | // Public functions 51 | //////////////////////// 52 | 53 | function name() 54 | public 55 | constant 56 | returns (string) 57 | { 58 | return NAME; 59 | } 60 | 61 | function symbol() 62 | public 63 | constant 64 | returns (string) 65 | { 66 | return SYMBOL; 67 | } 68 | 69 | function decimals() 70 | public 71 | constant 72 | returns (uint8) 73 | { 74 | return DECIMALS; 75 | } 76 | 77 | function version() 78 | public 79 | constant 80 | returns (string) 81 | { 82 | return VERSION; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/Helpers/TrustlessTokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./MTokenController.sol"; 4 | 5 | 6 | contract TrustlessTokenController is 7 | MTokenController 8 | { 9 | //////////////////////// 10 | // Internal functions 11 | //////////////////////// 12 | 13 | // 14 | // Implements MTokenController 15 | // 16 | 17 | function mOnTransfer( 18 | address /*from*/, 19 | address /*to*/, 20 | uint256 /*amount*/ 21 | ) 22 | internal 23 | returns (bool allow) 24 | { 25 | return true; 26 | } 27 | 28 | function mOnApprove( 29 | address /*owner*/, 30 | address /*spender*/, 31 | uint256 /*amount*/ 32 | ) 33 | internal 34 | returns (bool allow) 35 | { 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/StandardToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | import "../Standards/IERC20Token.sol"; 5 | import "../Standards/IERC677Token.sol"; 6 | import "../Standards/IERC677Callback.sol"; 7 | import "./BasicToken.sol"; 8 | import "./Helpers/TokenAllowance.sol"; 9 | 10 | 11 | /** 12 | * @title Standard ERC20 token 13 | * 14 | * @dev Implementation of the standard token. 15 | * @dev https://github.com/ethereum/EIPs/issues/20 16 | */ 17 | contract StandardToken is 18 | IERC20Token, 19 | BasicToken, 20 | TokenAllowance 21 | { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /contracts/SnapshotToken/ncd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/contracts/SnapshotToken/ncd.png -------------------------------------------------------------------------------- /contracts/Standards/IBasicToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IBasicToken { 5 | 6 | //////////////////////// 7 | // Events 8 | //////////////////////// 9 | 10 | event Transfer( 11 | address indexed from, 12 | address indexed to, 13 | uint256 amount 14 | ); 15 | 16 | //////////////////////// 17 | // Public functions 18 | //////////////////////// 19 | 20 | /// @dev This function makes it easy to get the total number of tokens 21 | /// @return The total number of tokens 22 | function totalSupply() 23 | public 24 | constant 25 | returns (uint256); 26 | 27 | /// @param owner The address that's balance is being requested 28 | /// @return The balance of `owner` at the current block 29 | function balanceOf(address owner) 30 | public 31 | constant 32 | returns (uint256 balance); 33 | 34 | /// @notice Send `amount` tokens to `to` from `msg.sender` 35 | /// @param to The address of the recipient 36 | /// @param amount The amount of tokens to be transferred 37 | /// @return Whether the transfer was successful or not 38 | function transfer(address to, uint256 amount) 39 | public 40 | returns (bool success); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /contracts/Standards/IClonedTokenParent.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./ITokenSnapshots.sol"; 4 | 5 | 6 | /// @title represents link between cloned and parent token 7 | /// @dev when token is clone from other token, initial balances of the cloned token 8 | /// correspond to balances of parent token at the moment of parent snapshot id specified 9 | /// @notice please note that other tokens beside snapshot token may be cloned 10 | contract IClonedTokenParent is ITokenSnapshots { 11 | 12 | //////////////////////// 13 | // Public functions 14 | //////////////////////// 15 | 16 | 17 | /// @return address of parent token, address(0) if root 18 | /// @dev parent token does not need to clonable, nor snapshottable, just a normal token 19 | function parentToken() 20 | public 21 | constant 22 | returns(IClonedTokenParent parent); 23 | 24 | /// @return snapshot at wchich initial token distribution was taken 25 | function parentSnapshotId() 26 | public 27 | constant 28 | returns(uint256 snapshotId); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/Standards/IContractId.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | /// @title uniquely identifies deployable (non-abstract) platform contract 4 | /// @notice cheap way of assigning implementations to knownInterfaces which represent system services 5 | /// unfortunatelly ERC165 does not include full public interface (ABI) and does not provide way to list implemented interfaces 6 | /// EIP820 still in the making 7 | /// @dev ids are generated as follows keccak256("neufund-platform:") 8 | /// ids roughly correspond to ABIs 9 | contract IContractId { 10 | /// @param id defined as above 11 | /// @param version implementation version 12 | function contractId() public pure returns (bytes32 id, uint256 version); 13 | } 14 | -------------------------------------------------------------------------------- /contracts/Standards/IERC20Allowance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IERC20Allowance { 5 | 6 | //////////////////////// 7 | // Events 8 | //////////////////////// 9 | 10 | event Approval( 11 | address indexed owner, 12 | address indexed spender, 13 | uint256 amount 14 | ); 15 | 16 | //////////////////////// 17 | // Public functions 18 | //////////////////////// 19 | 20 | /// @dev This function makes it easy to read the `allowed[]` map 21 | /// @param owner The address of the account that owns the token 22 | /// @param spender The address of the account able to transfer the tokens 23 | /// @return Amount of remaining tokens of owner that spender is allowed 24 | /// to spend 25 | function allowance(address owner, address spender) 26 | public 27 | constant 28 | returns (uint256 remaining); 29 | 30 | /// @notice `msg.sender` approves `spender` to spend `amount` tokens on 31 | /// its behalf. This is a modified version of the ERC20 approve function 32 | /// to be a little bit safer 33 | /// @param spender The address of the account able to transfer the tokens 34 | /// @param amount The amount of tokens to be approved for transfer 35 | /// @return True if the approval was successful 36 | function approve(address spender, uint256 amount) 37 | public 38 | returns (bool success); 39 | 40 | /// @notice Send `amount` tokens to `to` from `from` on the condition it 41 | /// is approved by `from` 42 | /// @param from The address holding the tokens being transferred 43 | /// @param to The address of the recipient 44 | /// @param amount The amount of tokens to be transferred 45 | /// @return True if the transfer was successful 46 | function transferFrom(address from, address to, uint256 amount) 47 | public 48 | returns (bool success); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /contracts/Standards/IERC20Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IBasicToken.sol"; 4 | import "./IERC20Allowance.sol"; 5 | 6 | 7 | contract IERC20Token is IBasicToken, IERC20Allowance { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /contracts/Standards/IERC223Callback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title current ERC223 fallback function 5 | /// @dev to be used in all future token contract 6 | /// @dev NEU and ICBMEtherToken (obsolete) are the only contracts that still uses IERC223LegacyCallback 7 | contract IERC223Callback { 8 | 9 | //////////////////////// 10 | // Public functions 11 | //////////////////////// 12 | 13 | function tokenFallback(address from, uint256 amount, bytes data) 14 | public; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /contracts/Standards/IERC223LegacyCallback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title old ERC223 callback function 5 | /// @dev as used in Neumark and ICBMEtherToken 6 | contract IERC223LegacyCallback { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | function onTokenTransfer(address from, uint256 amount, bytes data) 13 | public; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /contracts/Standards/IERC223Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IERC20Token.sol"; 4 | import "./ITokenMetadata.sol"; 5 | 6 | 7 | contract IERC223Token is IERC20Token, ITokenMetadata { 8 | 9 | /// @dev Departure: We do not log data, it has no advantage over a standard 10 | /// log event. By sticking to the standard log event we 11 | /// stay compatible with constracts that expect and ERC20 token. 12 | 13 | // event Transfer( 14 | // address indexed from, 15 | // address indexed to, 16 | // uint256 amount, 17 | // bytes data); 18 | 19 | 20 | /// @dev Departure: We do not use the callback on regular transfer calls to 21 | /// stay compatible with constracts that expect and ERC20 token. 22 | 23 | // function transfer(address to, uint256 amount) 24 | // public 25 | // returns (bool); 26 | 27 | //////////////////////// 28 | // Public functions 29 | //////////////////////// 30 | 31 | function transfer(address to, uint256 amount, bytes data) 32 | public 33 | returns (bool); 34 | } 35 | -------------------------------------------------------------------------------- /contracts/Standards/IERC677Allowance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IERC20Allowance.sol"; 4 | 5 | 6 | contract IERC677Allowance is IERC20Allowance { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | /// @notice `msg.sender` approves `spender` to send `amount` tokens on 13 | /// its behalf, and then a function is triggered in the contract that is 14 | /// being approved, `spender`. This allows users to use their tokens to 15 | /// interact with contracts in one function call instead of two 16 | /// @param spender The address of the contract able to transfer the tokens 17 | /// @param amount The amount of tokens to be approved for transfer 18 | /// @return True if the function call was successful 19 | function approveAndCall(address spender, uint256 amount, bytes extraData) 20 | public 21 | returns (bool success); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /contracts/Standards/IERC677Callback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IERC677Callback { 5 | 6 | //////////////////////// 7 | // Public functions 8 | //////////////////////// 9 | 10 | // NOTE: This call can be initiated by anyone. You need to make sure that 11 | // it is send by the token (`require(msg.sender == token)`) or make sure 12 | // amount is valid (`require(token.allowance(this) >= amount)`). 13 | function receiveApproval( 14 | address from, 15 | uint256 amount, 16 | address token, // IERC667Token 17 | bytes data 18 | ) 19 | public 20 | returns (bool success); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /contracts/Standards/IERC677Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IERC20Token.sol"; 4 | import "./IERC677Allowance.sol"; 5 | 6 | 7 | contract IERC677Token is IERC20Token, IERC677Allowance { 8 | } 9 | -------------------------------------------------------------------------------- /contracts/Standards/IEthereumForkArbiter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IEthereumForkArbiter { 5 | 6 | //////////////////////// 7 | // Events 8 | //////////////////////// 9 | 10 | event LogForkAnnounced( 11 | string name, 12 | string url, 13 | uint256 blockNumber 14 | ); 15 | 16 | event LogForkSigned( 17 | uint256 blockNumber, 18 | bytes32 blockHash 19 | ); 20 | 21 | //////////////////////// 22 | // Public functions 23 | //////////////////////// 24 | 25 | function nextForkName() 26 | public 27 | constant 28 | returns (string); 29 | 30 | function nextForkUrl() 31 | public 32 | constant 33 | returns (string); 34 | 35 | function nextForkBlockNumber() 36 | public 37 | constant 38 | returns (uint256); 39 | 40 | function lastSignedBlockNumber() 41 | public 42 | constant 43 | returns (uint256); 44 | 45 | function lastSignedBlockHash() 46 | public 47 | constant 48 | returns (bytes32); 49 | 50 | function lastSignedTimestamp() 51 | public 52 | constant 53 | returns (uint256); 54 | 55 | } 56 | -------------------------------------------------------------------------------- /contracts/Standards/IFeeDisbursalController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | import "../Standards/IContractId.sol"; 3 | 4 | 5 | /// @title granular fee disbursal controller 6 | contract IFeeDisbursalController is 7 | IContractId 8 | { 9 | 10 | 11 | //////////////////////// 12 | // Public functions 13 | //////////////////////// 14 | 15 | /// @notice check whether claimer can accept disbursal offer 16 | function onAccept(address /*token*/, address /*proRataToken*/, address claimer) 17 | public 18 | constant 19 | returns (bool allow); 20 | 21 | /// @notice check whether claimer can reject disbursal offer 22 | function onReject(address /*token*/, address /*proRataToken*/, address claimer) 23 | public 24 | constant 25 | returns (bool allow); 26 | 27 | /// @notice check wether this disbursal can happen 28 | function onDisburse(address token, address disburser, uint256 amount, address proRataToken, uint256 recycleAfterPeriod) 29 | public 30 | constant 31 | returns (bool allow); 32 | 33 | /// @notice check wether this recycling can happen 34 | function onRecycle(address token, address /*proRataToken*/, address[] investors, uint256 until) 35 | public 36 | constant 37 | returns (bool allow); 38 | 39 | /// @notice check wether the disbursal controller may be changed 40 | function onChangeFeeDisbursalController(address sender, IFeeDisbursalController newController) 41 | public 42 | constant 43 | returns (bool); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /contracts/Standards/IMigrationChain.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | /// @title contract upgrade pattern where all implementations are linked 4 | /// @dev actual migration function performed in new implementation is not defined in the interface 5 | contract IMigrationChain { 6 | 7 | //////////////////////// 8 | // Events 9 | //////////////////////// 10 | 11 | event LogMigratedTo( 12 | address oldImpl, 13 | address newImpl 14 | ); 15 | 16 | //////////////////////// 17 | // Interface Methods 18 | //////////////////////// 19 | 20 | // start migrating actual implementation into new implementation 21 | function startMigrateTo(IMigrationChain newImpl) 22 | public; 23 | 24 | // finish migrating actual implemnetation into new implementation 25 | function finishMigrateTo(IMigrationChain newImpl) 26 | public; 27 | 28 | 29 | // address of new implementation 30 | /// @dev should return zero address if not migrated 31 | function migratedTo() 32 | public 33 | constant 34 | returns (IMigrationChain); 35 | 36 | // returns true if current implementation is being migrated to new implementation 37 | function isMigrating() 38 | public 39 | constant 40 | returns (bool); 41 | 42 | // link back to old implementation 43 | /// @dev should return zero address if is the first controller 44 | function migratedFrom() 45 | public 46 | constant 47 | returns (address); 48 | } 49 | -------------------------------------------------------------------------------- /contracts/Standards/IPlatformPortfolio.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "./IERC223Callback.sol"; 4 | 5 | 6 | /// @title disburse payment token amount to snapshot token holders 7 | /// @dev payment token received via ERC223 Transfer 8 | contract IPlatformPortfolio is IERC223Callback { 9 | // TODO: declare interface 10 | } 11 | -------------------------------------------------------------------------------- /contracts/Standards/ISnapshotable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title advances snapshot id on demand 5 | /// @dev see Snapshot folder for implementation examples ie. DailyAndSnapshotable contract 6 | contract ISnapshotable { 7 | 8 | //////////////////////// 9 | // Events 10 | //////////////////////// 11 | 12 | /// @dev should log each new snapshot id created, including snapshots created automatically via MSnapshotPolicy 13 | event LogSnapshotCreated(uint256 snapshotId); 14 | 15 | //////////////////////// 16 | // Public functions 17 | //////////////////////// 18 | 19 | /// always creates new snapshot id which gets returned 20 | /// however, there is no guarantee that any snapshot will be created with this id, this depends on the implementation of MSnaphotPolicy 21 | function createSnapshot() 22 | public 23 | returns (uint256); 24 | 25 | /// upper bound of series snapshotIds for which there's a value 26 | function currentSnapshotId() 27 | public 28 | constant 29 | returns (uint256); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/Standards/ITokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title granular token controller based on MSnapshotToken observer pattern 5 | contract ITokenController { 6 | 7 | //////////////////////// 8 | // Public functions 9 | //////////////////////// 10 | 11 | /// @notice see MTokenTransferController 12 | /// @dev additionally passes broker that is executing transaction between from and to 13 | /// for unbrokered transfer, broker == from 14 | function onTransfer(address broker, address from, address to, uint256 amount) 15 | public 16 | constant 17 | returns (bool allow); 18 | 19 | /// @notice see MTokenAllowanceController 20 | function onApprove(address owner, address spender, uint256 amount) 21 | public 22 | constant 23 | returns (bool allow); 24 | 25 | /// @notice see MTokenMint 26 | function onGenerateTokens(address sender, address owner, uint256 amount) 27 | public 28 | constant 29 | returns (bool allow); 30 | 31 | /// @notice see MTokenMint 32 | function onDestroyTokens(address sender, address owner, uint256 amount) 33 | public 34 | constant 35 | returns (bool allow); 36 | 37 | /// @notice controls if sender can change controller to newController 38 | /// @dev for this to succeed TYPICALLY current controller must be already migrated to a new one 39 | function onChangeTokenController(address sender, address newController) 40 | public 41 | constant 42 | returns (bool); 43 | 44 | /// @notice overrides spender allowance 45 | /// @dev may be used to implemented forced transfers in which token controller may override approved allowance 46 | /// with any > 0 value and then use transferFrom to execute such transfer 47 | /// This by definition creates non-trustless token so do not implement this call if you do not need trustless transfers! 48 | /// Implementer should not allow approve() to be executed if there is an overrride 49 | // Implemented should return allowance() taking into account override 50 | function onAllowance(address owner, address spender) 51 | public 52 | constant 53 | returns (uint256 allowanceOverride); 54 | } 55 | -------------------------------------------------------------------------------- /contracts/Standards/ITokenControllerHook.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title hooks token controller to token contract and allows to replace it 5 | contract ITokenControllerHook { 6 | 7 | //////////////////////// 8 | // Events 9 | //////////////////////// 10 | 11 | event LogChangeTokenController( 12 | address oldController, 13 | address newController, 14 | address by 15 | ); 16 | 17 | //////////////////////// 18 | // Public functions 19 | //////////////////////// 20 | 21 | /// @notice replace current token controller 22 | /// @dev please note that this process is also controlled by existing controller 23 | function changeTokenController(address newController) 24 | public; 25 | 26 | /// @notice returns current controller 27 | function tokenController() 28 | public 29 | constant 30 | returns (address currentController); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /contracts/Standards/ITokenExchangeRateOracle.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract ITokenExchangeRateOracle { 5 | /// @notice provides actual price of 'numeratorToken' in 'denominatorToken' 6 | /// returns timestamp at which price was obtained in oracle 7 | function getExchangeRate(address numeratorToken, address denominatorToken) 8 | public 9 | constant 10 | returns (uint256 rateFraction, uint256 timestamp); 11 | 12 | /// @notice allows to retreive multiple exchange rates in once call 13 | function getExchangeRates(address[] numeratorTokens, address[] denominatorTokens) 14 | public 15 | constant 16 | returns (uint256[] rateFractions, uint256[] timestamps); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/Standards/ITokenMetadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract ITokenMetadata { 5 | 6 | //////////////////////// 7 | // Public functions 8 | //////////////////////// 9 | 10 | function symbol() 11 | public 12 | constant 13 | returns (string); 14 | 15 | function name() 16 | public 17 | constant 18 | returns (string); 19 | 20 | function decimals() 21 | public 22 | constant 23 | returns (uint8); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/Standards/ITokenSnapshots.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | /// @title access to snapshots of a token 5 | /// @notice allows to implement complex token holder rights like revenue disbursal or voting 6 | /// @notice snapshots are series of values with assigned ids. ids increase strictly. particular id mechanism is not assumed 7 | contract ITokenSnapshots { 8 | 9 | //////////////////////// 10 | // Public functions 11 | //////////////////////// 12 | 13 | /// @notice Total amount of tokens at a specific `snapshotId`. 14 | /// @param snapshotId of snapshot at which totalSupply is queried 15 | /// @return The total amount of tokens at `snapshotId` 16 | /// @dev reverts on snapshotIds greater than currentSnapshotId() 17 | /// @dev returns 0 for snapshotIds less than snapshotId of first value 18 | function totalSupplyAt(uint256 snapshotId) 19 | public 20 | constant 21 | returns(uint256); 22 | 23 | /// @dev Queries the balance of `owner` at a specific `snapshotId` 24 | /// @param owner The address from which the balance will be retrieved 25 | /// @param snapshotId of snapshot at which the balance is queried 26 | /// @return The balance at `snapshotId` 27 | function balanceOfAt(address owner, uint256 snapshotId) 28 | public 29 | constant 30 | returns (uint256); 31 | 32 | /// @notice upper bound of series of snapshotIds for which there's a value in series 33 | /// @return snapshotId 34 | function currentSnapshotId() 35 | public 36 | constant 37 | returns (uint256); 38 | } 39 | -------------------------------------------------------------------------------- /contracts/Standards/IWithdrawableToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract IWithdrawableToken { 5 | 6 | //////////////////////// 7 | // Public functions 8 | //////////////////////// 9 | 10 | /// @notice withdraws from a token holding assets 11 | /// @dev amount of asset should be returned to msg.sender and corresponding balance burned 12 | function withdraw(uint256 amount) 13 | public; 14 | } 15 | -------------------------------------------------------------------------------- /contracts/VotingCenter/IVotingController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IContractId.sol"; 4 | 5 | 6 | contract IVotingController is IContractId { 7 | // token must be NEU or equity token 8 | // if initiator is not equity token then proposals start in campaign mode 9 | // if token is NEU then default values must apply 10 | function onAddProposal(bytes32 proposalId, address initiator, address token) 11 | public 12 | constant 13 | returns (bool); 14 | 15 | /// @notice check wether the disbursal controller may be changed 16 | function onChangeVotingController(address sender, IVotingController newController) 17 | public 18 | constant 19 | returns (bool); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/VotingCenter/IVotingObserver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | /// @notice should be implemented by all contracts that initate the voting center procedure 4 | /// must be implemented by all contracts that initate voting procedure AND request observer callbacks 5 | contract IVotingObserver { 6 | /// @notice if requested, voting center will pass state transitions of proposal to observer 7 | /// @dev refer to VotingProposal for state variable values 8 | function onProposalStateTransition( 9 | bytes32 proposalId, 10 | uint8 oldState, 11 | uint8 newState) 12 | public; 13 | 14 | /// @notice only observer may tell if vote was in favor or not, voting center only carries on voting procedure 15 | /// example is equity token controller as observer which will count outcome as passed depending on company bylaws 16 | /// @param votingCenter at which voting center to look for the results 17 | /// @param proposalId for which proposalId to deliver results 18 | /// @return true means inFavor, false means agains, revert means that procedure is not yet final or any other problem 19 | /// @dev please note the revert/false distinction above, do not returns false in case voting is unknown or not yet final 20 | function votingResult(address votingCenter, bytes32 proposalId) 21 | public 22 | constant 23 | returns (bool inFavor); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/test/Company/MockEquityToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Company/EquityToken.sol"; 4 | import "../MockSnapshotIdToken.sol"; 5 | 6 | 7 | contract MockEquityToken is 8 | EquityToken, 9 | MockSnapshotIdToken 10 | { 11 | 12 | //////////////////////// 13 | // Constructor 14 | //////////////////////// 15 | 16 | constructor( 17 | Universe universe, 18 | IEquityTokenController controller, 19 | ETOTokenTerms etoTokenTerms, 20 | address nominee, 21 | address companyLegalRep 22 | ) 23 | EquityToken(universe, controller, etoTokenTerms, nominee, companyLegalRep) 24 | public 25 | {} 26 | } 27 | -------------------------------------------------------------------------------- /contracts/test/Company/TestMockableEquityTokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Universe.sol"; 4 | import "../../Agreement.sol"; 5 | import "../../ETO/IETOCommitmentObserver.sol"; 6 | import "../../Company/IEquityTokenController.sol"; 7 | import "../TestMockableTokenController.sol"; 8 | 9 | 10 | contract TestMockableEquityTokenController is 11 | IEquityTokenController, 12 | IETOCommitmentObserver, 13 | TestMockableTokenController, 14 | Agreement 15 | { 16 | 17 | //////////////////////// 18 | // Mutable state 19 | //////////////////////// 20 | 21 | bool internal _allowChangeNominee; 22 | 23 | //////////////////////// 24 | // Constructor 25 | //////////////////////// 26 | 27 | constructor( 28 | Universe universe 29 | ) 30 | public 31 | Agreement(universe.accessPolicy(), universe.forkArbiter()) 32 | { 33 | _allowChangeNominee = true; 34 | } 35 | 36 | //////////////////////// 37 | // Public Methods 38 | //////////////////////// 39 | 40 | // 41 | // Implements IEquityTokenController 42 | // 43 | 44 | function onChangeNominee(address, address, address) 45 | public 46 | constant 47 | returns (bool) 48 | { 49 | return _allowChangeNominee; 50 | } 51 | 52 | // 53 | // IERC223TokenCallback (proceeds disbursal) 54 | // 55 | 56 | /// allows contract to receive and distribure proceeds 57 | function tokenFallback(address, uint256, bytes) 58 | public 59 | { 60 | } 61 | 62 | // 63 | // Implements IETOCommitmentObserver 64 | // 65 | 66 | function onStateTransition(ETOState, ETOState) 67 | public 68 | { 69 | // msg.sender is ETOCommitment 70 | } 71 | 72 | // 73 | // Mock functions 74 | // 75 | 76 | function setAllowChangeNominee(bool allow) 77 | public 78 | { 79 | _allowChangeNominee = allow; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /contracts/test/CurveGas.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../NeumarkIssuanceCurve.sol"; 4 | 5 | 6 | contract CurveGas is NeumarkIssuanceCurve { 7 | 8 | //////////////////////// 9 | // External functions 10 | //////////////////////// 11 | 12 | function cumulativeWithGas(uint256 n) 13 | external 14 | constant 15 | returns (uint256, uint256) 16 | { 17 | uint256 start = gasleft(); 18 | uint256 result = cumulative(n); 19 | uint256 finish = gasleft(); 20 | return (result, start - finish); 21 | } 22 | 23 | function incrementalInverseWithGas(uint256 totalEuroUlps, uint256 neumarkUlps) 24 | external 25 | constant 26 | returns (uint256, uint256) 27 | { 28 | uint256 start = gasleft(); 29 | uint256 result = incrementalInverse(totalEuroUlps, neumarkUlps); 30 | uint256 finish = gasleft(); 31 | return (result, start - finish); 32 | } 33 | 34 | function incrementalInverseWithGas(uint256 totalEuroUlps, uint256 neumarkUlps, uint256 minEurUlps, uint256 maxEurUlps) 35 | external 36 | constant 37 | returns (uint256, uint256) 38 | { 39 | uint256 start = gasleft(); 40 | uint256 result = incrementalInverse(totalEuroUlps, neumarkUlps, minEurUlps, maxEurUlps); 41 | uint256 finish = gasleft(); 42 | return (result, start - finish); 43 | } 44 | 45 | function cumulativeInverseWithGas(uint256 neumarkUlps, uint256 minEurUlps, uint256 maxEurUlps) 46 | external 47 | constant 48 | returns (uint256, uint256) 49 | { 50 | uint256 start = gasleft(); 51 | uint256 result = cumulativeInverse(neumarkUlps, minEurUlps, maxEurUlps); 52 | uint256 finish = gasleft(); 53 | return (result, start - finish); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /contracts/test/ETO/MockETOTermsConstraints.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../ETO/ETOTermsConstraints.sol"; 4 | 5 | contract MockETOTermsConstraints is ETOTermsConstraints { 6 | 7 | //////////////////////// 8 | // Immutable state 9 | //////////////////////// 10 | 11 | // you can start your ETO in 5 minutes on dev 12 | uint256 public constant DATE_TO_WHITELIST_MIN_DURATION = 8 hours; 13 | 14 | // claim duration is 1 day minimum 15 | uint256 public constant MIN_CLAIM_DURATION = 8 hours; 16 | 17 | //////////////////////// 18 | // Constructor 19 | //////////////////////// 20 | 21 | constructor( 22 | bool canSetTransferability, 23 | bool hasNominee, 24 | uint256 minTicketSizeEurUlps, 25 | uint256 maxTicketSizeEurUlps, 26 | uint256 minInvestmentAmountEurUlps, 27 | uint256 maxInvestmentAmountEurUlps, 28 | string name, 29 | OfferingDocumentType offeringDocumentType, 30 | OfferingDocumentSubType offeringDocumentSubType, 31 | string jurisdiction, 32 | AssetType assetType, 33 | address tokenOfferingOperator 34 | ) 35 | public 36 | ETOTermsConstraints( 37 | canSetTransferability, 38 | hasNominee, 39 | minTicketSizeEurUlps, 40 | maxTicketSizeEurUlps, 41 | minInvestmentAmountEurUlps, 42 | maxInvestmentAmountEurUlps, 43 | name, 44 | offeringDocumentType, 45 | offeringDocumentSubType, 46 | jurisdiction, 47 | assetType, 48 | tokenOfferingOperator 49 | ) 50 | {} 51 | } 52 | -------------------------------------------------------------------------------- /contracts/test/ETO/MockUncheckedETOTokenTerms.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../ETO/ETOTokenTerms.sol"; 4 | 5 | 6 | /// @title does not check max tokens and max funds 7 | contract MockUncheckedETOTokenTerms is ETOTokenTerms { 8 | 9 | 10 | //////////////////////// 11 | // Constructor 12 | //////////////////////// 13 | 14 | constructor( 15 | string equityTokenName, 16 | string equityTokenSymbol, 17 | string isin, 18 | uint256 minNumberOfTokens, 19 | uint256 maxNumberOfTokens, 20 | uint256 tokenPriceEurUlps, 21 | uint256 maxNumberOfTokensInWhitelist, 22 | uint256 shareNominalValueUlps, 23 | uint256 shareNominalValueEurUlps, 24 | uint256 equityTokensPerShare, 25 | uint8 equityTokenDecimals 26 | ) 27 | public 28 | // do not pass max, min ticket etc. to disable overflow checks 29 | ETOTokenTerms( 30 | equityTokenName, 31 | equityTokenSymbol, 32 | isin, 33 | equityTokensPerShare, 34 | equityTokensPerShare, 35 | equityTokensPerShare, 36 | equityTokensPerShare, 37 | shareNominalValueUlps, 38 | shareNominalValueEurUlps, 39 | equityTokensPerShare, 40 | equityTokenDecimals 41 | ) 42 | { 43 | require(maxNumberOfTokensInWhitelist <= maxNumberOfTokens, "NF_WL_TOKENS_GT_MAX_TOKENS"); 44 | require(maxNumberOfTokens >= minNumberOfTokens, "NF_MIN_TOKENS_GT_MAX_TOKENS"); 45 | // min cap must be > single share 46 | require(minNumberOfTokens >= equityTokensPerShare, "NF_ETO_TERMS_ONE_SHARE"); 47 | 48 | MIN_NUMBER_OF_TOKENS = minNumberOfTokens; 49 | MAX_NUMBER_OF_TOKENS = maxNumberOfTokens; 50 | TOKEN_PRICE_EUR_ULPS = tokenPriceEurUlps; 51 | MAX_NUMBER_OF_TOKENS_IN_WHITELIST = maxNumberOfTokensInWhitelist; 52 | EQUITY_TOKENS_PER_SHARE = equityTokensPerShare; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /contracts/test/ForceEther.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract ForceEther { 5 | 6 | //////////////////////// 7 | // Constructor 8 | //////////////////////// 9 | 10 | constructor() 11 | payable 12 | public 13 | {} 14 | 15 | //////////////////////// 16 | // Public functions 17 | //////////////////////// 18 | 19 | function pay(address target) public { 20 | // On selfdestruct ether is transfered without 21 | // involving the callback function. 22 | selfdestruct(target); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contracts/test/ICBM/MockICBMCommitment.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../../ICBM/Commitment/ICBMCommitment.sol"; 4 | 5 | 6 | contract MockICBMCommitment is 7 | ICBMCommitment 8 | { 9 | //////////////////////// 10 | // Constructor 11 | //////////////////////// 12 | 13 | constructor( 14 | IAccessPolicy accessPolicy, 15 | IEthereumForkArbiter forkArbiter, 16 | int256 startDate, 17 | address platformWallet, 18 | Neumark neumark, 19 | ICBMEtherToken etherToken, 20 | ICBMEuroToken euroToken, 21 | ICBMLockedAccount etherLock, 22 | ICBMLockedAccount euroLock, 23 | uint256 capEurUlps, 24 | uint256 minTicketEurUlps, 25 | uint256 ethEurFraction 26 | ) 27 | ICBMCommitment(accessPolicy, forkArbiter, startDate, platformWallet, neumark, 28 | etherToken, euroToken, etherLock, euroLock, capEurUlps, minTicketEurUlps, ethEurFraction) 29 | public 30 | { 31 | } 32 | 33 | //////////////////////// 34 | // Mocked functions 35 | //////////////////////// 36 | 37 | /// allows to force any state within commitment contract 38 | function _mockTransitionTo(State newState) public { 39 | transitionTo(newState); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /contracts/test/ICBM/TestFeeDistributionPool.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../Standards/IERC677Callback.sol"; 4 | import "../../Standards/IERC223Callback.sol"; 5 | import "../../Standards/IERC677Token.sol"; 6 | import "../../Serialization.sol"; 7 | 8 | 9 | contract TestFeeDistributionPool is 10 | IERC677Callback, 11 | IERC223Callback 12 | { 13 | 14 | //////////////////////// 15 | // Events 16 | //////////////////////// 17 | 18 | event LogTestReceiveApproval( 19 | address from, 20 | uint256 amount 21 | ); 22 | 23 | event LogTestReceiveTransfer( 24 | address paymentToken, 25 | address snapshotToken, 26 | uint256 amount, 27 | address from 28 | ); 29 | 30 | //////////////////////// 31 | // Public functions 32 | //////////////////////// 33 | 34 | // 35 | // Implements IERC677Callback 36 | // 37 | 38 | function receiveApproval( 39 | address from, 40 | uint256 _amount, 41 | address _token, 42 | bytes // _data 43 | ) 44 | public 45 | returns (bool) 46 | { 47 | require(msg.sender == _token); 48 | require(IERC677Token(_token).transferFrom(from, address(this), _amount)); 49 | emit LogTestReceiveApproval(from, _amount); 50 | return true; 51 | } 52 | 53 | // 54 | // Implements IERC223Callback 55 | // 56 | 57 | function tokenFallback(address from, uint256 amount, bytes snapshotTokenEncoded) 58 | public 59 | { 60 | address snapshotToken = Serialization.decodeAddress(snapshotTokenEncoded); 61 | emit LogTestReceiveTransfer(msg.sender, snapshotToken, amount, from); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /contracts/test/ICBM/TestICBMEuroTokenMigrationTarget.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../SnapshotToken/StandardToken.sol"; 4 | import "../../ICBM/IMigrationSource.sol"; 5 | import "../../SnapshotToken/Helpers/TrustlessTokenController.sol"; 6 | import "../../ICBM/ICBMEuroTokenMigrationTarget.sol"; 7 | 8 | 9 | contract TestICBMEuroTokenMigrationTarget is 10 | StandardToken, 11 | TrustlessTokenController, 12 | ICBMEuroTokenMigrationTarget 13 | { 14 | //////////////////////// 15 | // Immutable state 16 | //////////////////////// 17 | 18 | address private MIGRATION_SOURCE; 19 | 20 | //////////////////////// 21 | // Constructor 22 | //////////////////////// 23 | 24 | constructor(address migrationSource) 25 | public 26 | { 27 | MIGRATION_SOURCE = migrationSource; 28 | } 29 | 30 | //////////////////////// 31 | // Public Methods 32 | //////////////////////// 33 | 34 | // 35 | // Implements EuroTokenMigrationTarget 36 | 37 | function migrateEuroTokenOwner(address owner, uint256 amount) 38 | public 39 | onlyMigrationSource() 40 | { 41 | deposit(owner, amount); 42 | } 43 | 44 | // 45 | // Implements IMigrationTarget 46 | // 47 | 48 | function currentMigrationSource() 49 | public 50 | constant 51 | returns (address) 52 | { 53 | return address(MIGRATION_SOURCE); 54 | } 55 | 56 | //////////////////////// 57 | // Private Methods 58 | //////////////////////// 59 | 60 | function deposit(address to, uint256 amount) private { 61 | require(to != address(0)); 62 | _balances[to] = Math.add(_balances[to], amount); 63 | _totalSupply = Math.add(_totalSupply, amount); 64 | emit Transfer(address(0), to, amount); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/test/ICBM/TestICBMLockedAccountController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../../ICBM/ICBMLockedAccount.sol"; 4 | 5 | 6 | contract TestICBMLockedAccountController { 7 | 8 | //////////////////////// 9 | // Events 10 | //////////////////////// 11 | 12 | // this will make truffle to find this event in receipt 13 | event LogFundsLocked( 14 | address indexed investor, 15 | uint256 amount, 16 | uint256 neumarks 17 | ); 18 | 19 | //////////////////////// 20 | // Immutable state 21 | //////////////////////// 22 | 23 | ICBMLockedAccount private LOCKED_ACCOUNT; 24 | 25 | //////////////////////// 26 | // Constructor 27 | //////////////////////// 28 | 29 | constructor(ICBMLockedAccount lockedAccount) public { 30 | LOCKED_ACCOUNT = lockedAccount; 31 | } 32 | 33 | //////////////////////// 34 | // Public functions 35 | //////////////////////// 36 | 37 | function succ() 38 | public 39 | { 40 | LOCKED_ACCOUNT.controllerSucceeded(); 41 | } 42 | 43 | function fail() 44 | public 45 | { 46 | LOCKED_ACCOUNT.controllerFailed(); 47 | } 48 | 49 | // must deposit token for this investor and then investor makes allowance then call this function 50 | function investToken(uint256 neumarks) 51 | public 52 | { 53 | uint256 amount = LOCKED_ACCOUNT.assetToken().allowance(msg.sender, this); 54 | LOCKED_ACCOUNT.assetToken().transferFrom(msg.sender, this, amount); 55 | 56 | // make allowance for lock 57 | require(LOCKED_ACCOUNT.assetToken().approve(address(LOCKED_ACCOUNT), amount)); 58 | // lock in lock 59 | LOCKED_ACCOUNT.lock(msg.sender, amount, neumarks); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/test/ICBM/TestICBMTimedStateMachine.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../../ICBM/Commitment/ICBMTimedStateMachine.sol"; 4 | 5 | 6 | contract TestICBMTimedStateMachine is 7 | ICBMTimedStateMachine 8 | { 9 | //////////////////////// 10 | // Constructor 11 | //////////////////////// 12 | 13 | constructor(int256 whitelistStart) 14 | ICBMTimedStateMachine(whitelistStart) 15 | public 16 | { 17 | } 18 | 19 | //////////////////////// 20 | // Public Methods 21 | //////////////////////// 22 | 23 | function testStateOrdering() 24 | public 25 | pure 26 | returns (bool passed) 27 | { 28 | assert(State.Before == State.Before); 29 | assert(State.Before < State.Whitelist); 30 | assert(State.Before < State.Public); 31 | assert(State.Before < State.Finished); 32 | 33 | assert(State.Whitelist > State.Before); 34 | assert(State.Whitelist == State.Whitelist); 35 | assert(State.Whitelist < State.Public); 36 | assert(State.Whitelist < State.Finished); 37 | 38 | assert(State.Public > State.Before); 39 | assert(State.Public > State.Whitelist); 40 | assert(State.Public == State.Public); 41 | assert(State.Public < State.Finished); 42 | 43 | assert(State.Finished > State.Before); 44 | assert(State.Finished > State.Whitelist); 45 | assert(State.Finished > State.Public); 46 | assert(State.Finished == State.Finished); 47 | 48 | assert(State.Public <= State.Public); 49 | assert(State.Public >= State.Public); 50 | 51 | assert(int(State.Before) + 1 == int(State.Whitelist)); 52 | assert(int(State.Whitelist) + 1 == int(State.Public)); 53 | assert(int(State.Public) + 1 == int(State.Finished)); 54 | 55 | return true; 56 | } 57 | 58 | // 59 | // MStateMachine default implementations 60 | // 61 | 62 | function mAfterTransition(State /* oldState */, State /* newState */) 63 | internal 64 | { 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/test/MockSnapshotIdToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../SnapshotToken/StandardSnapshotToken.sol"; 4 | 5 | 6 | contract MockSnapshotIdToken is StandardSnapshotToken { 7 | 8 | //////////////////////// 9 | // Mutable state 10 | //////////////////////// 11 | 12 | // list of all known holders 13 | address[] private _holders; 14 | 15 | //////////////////////// 16 | // Public functions 17 | //////////////////////// 18 | 19 | function _decreaseSnapshots(uint256 delta) public { 20 | // decrease total supply 21 | shiftSnapshots(_totalSupplyValues, delta); 22 | // decreases snapshots for all token holders 23 | for(uint256 ii = 0; ii < _holders.length; ii += 1) { 24 | shiftSnapshots(_balances[_holders[ii]], delta); 25 | } 26 | } 27 | 28 | function _allHolders() 29 | public 30 | constant 31 | returns (address[]) 32 | { 33 | return _holders; 34 | } 35 | 36 | //////////////////////// 37 | // Internal functions 38 | //////////////////////// 39 | 40 | // 41 | // Implements MTokenTransfer 42 | // 43 | 44 | function mTransfer( 45 | address from, 46 | address to, 47 | uint256 amount 48 | ) 49 | internal 50 | { 51 | addHolder(to); 52 | BasicSnapshotToken.mTransfer(from, to, amount); 53 | } 54 | 55 | // 56 | // Implements MTokenMinst 57 | // 58 | 59 | function mGenerateTokens(address owner, uint256 amount) 60 | internal 61 | { 62 | addHolder(owner); 63 | MintableSnapshotToken.mGenerateTokens(owner, amount); 64 | } 65 | 66 | //////////////////////// 67 | // Private functions 68 | //////////////////////// 69 | 70 | function addHolder(address holder) 71 | private 72 | { 73 | // if there are no snapshots we have a new holder 74 | if(!hasValue(_balances[holder])) { 75 | _holders.push(holder); 76 | } 77 | } 78 | 79 | function shiftSnapshots(Values[] storage values, uint256 delta) 80 | private 81 | { 82 | for(uint256 ii = 0; ii < values.length; ii += 1) { 83 | values[ii].snapshotId -= delta; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /contracts/test/MockVotingCenter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../VotingCenter/VotingCenter.sol"; 4 | 5 | 6 | contract MockVotingCenter is VotingCenter { 7 | 8 | //////////////////////// 9 | // Constructor 10 | //////////////////////// 11 | 12 | constructor(IVotingController controller) 13 | public 14 | VotingCenter(controller) 15 | {} 16 | 17 | //////////////////////// 18 | // Public functions 19 | //////////////////////// 20 | 21 | function _shiftProposalDeadlines(bytes32 proposalId, uint256 delta) 22 | public 23 | { 24 | VotingProposal.Proposal storage p = ensureExistingProposal(proposalId); 25 | uint32[5] storage deadlines = p.deadlines; 26 | for(uint256 ii; ii < 5; ii += 1) { 27 | // storage writes not optimized. this is mock function never deployed on mainnet 28 | // so optimization disregarded 29 | deadlines[ii] = uint32(Math.sub(deadlines[ii], delta)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /contracts/test/TestAccessControl.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../AccessControl/AccessControlled.sol"; 4 | import "../AccessControl/RoleBasedAccessPolicy.sol"; 5 | 6 | 7 | contract TestAccessControlExampleRoles { 8 | 9 | //////////////////////// 10 | // Constants 11 | //////////////////////// 12 | 13 | // keccak256("Example") 14 | bytes32 internal constant ROLE_EXAMPLE = 0xb01f6215887f913abe74277c39da2c7de51baf17958191658f84959dfddab970; 15 | } 16 | 17 | 18 | contract TestAccessControl is AccessControlled, TestAccessControlExampleRoles { 19 | 20 | //////////////// 21 | // Types 22 | //////////////// 23 | 24 | // Łukasiewicz logic values 25 | enum TriState { 26 | Unset, 27 | Allow, 28 | Deny 29 | } 30 | 31 | //////////////////////// 32 | // Events 33 | //////////////////////// 34 | 35 | /// @dev just to have events ABIs as truffle will not handle events from internal transactions to other contracts 36 | event LogAccessChanged( 37 | address controller, 38 | address indexed subject, 39 | bytes32 role, 40 | IAccessControlled indexed object, 41 | TriState oldValue, 42 | TriState newValue 43 | ); 44 | 45 | event LogAccess( 46 | address indexed subject, 47 | bytes32 role, 48 | IAccessControlled indexed object, 49 | bytes4 verb, 50 | bool granted 51 | ); 52 | 53 | //////////////////////// 54 | // Constructor 55 | //////////////////////// 56 | 57 | constructor(IAccessPolicy policy) 58 | AccessControlled(policy) 59 | public 60 | { 61 | } 62 | 63 | //////////////////////// 64 | // Public functions 65 | //////////////////////// 66 | 67 | function someFunction() 68 | public 69 | only(ROLE_EXAMPLE) 70 | { 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /contracts/test/TestAgreement.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../AccessControl/AccessControlled.sol"; 4 | import "../Agreement.sol"; 5 | 6 | 7 | contract TestAgreement is 8 | AccessControlled, 9 | Agreement 10 | { 11 | //////////////////////// 12 | // Constructor 13 | //////////////////////// 14 | 15 | constructor(IAccessPolicy accessPolicy, IEthereumForkArbiter forkArbiter) 16 | Agreement(accessPolicy, forkArbiter) 17 | public 18 | { 19 | } 20 | 21 | //////////////////////// 22 | // Public functions 23 | //////////////////////// 24 | 25 | function signMeUp() 26 | public 27 | acceptAgreement(msg.sender) 28 | { 29 | } 30 | 31 | function signMeUpAgain() 32 | public 33 | acceptAgreement(msg.sender) 34 | { 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/test/TestDisburser.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IERC223Callback.sol"; 4 | import "../Standards/IERC223Token.sol"; 5 | 6 | 7 | contract TestDisburser is 8 | IERC223Callback 9 | { 10 | //////////////////////// 11 | // Mutable state 12 | /////////////////////// 13 | 14 | address private SNAPSHOT_TOKEN; 15 | IERC223Callback private FEE_DISBURSAL; 16 | 17 | //////////////////////// 18 | // Mutable state 19 | /////////////////////// 20 | 21 | uint256 private _recycleAfterDuration; 22 | 23 | //////////////////////// 24 | // Constructor 25 | //////////////////////// 26 | 27 | constructor(IERC223Callback feeDisbursal, address snapshotToken) 28 | public 29 | { 30 | FEE_DISBURSAL = feeDisbursal; 31 | SNAPSHOT_TOKEN = snapshotToken; 32 | } 33 | 34 | //////////////////////// 35 | // Public functions 36 | //////////////////////// 37 | 38 | function tokenFallback(address /*from*/, uint256 amount, bytes /*data*/) 39 | public 40 | { 41 | bytes memory data; 42 | if (_recycleAfterDuration == 0) { 43 | data = abi.encodePacked(address(SNAPSHOT_TOKEN)); 44 | } else { 45 | data = abi.encodePacked(address(SNAPSHOT_TOKEN), _recycleAfterDuration); 46 | } 47 | // we must have ROLE_DISBURSER to forward to fee disbursal 48 | IERC223Token token = IERC223Token(msg.sender); 49 | // we forward amount just received to disbursal via original token 50 | assert(token.transfer(FEE_DISBURSAL, amount, data)); 51 | } 52 | 53 | function setRecycleAfterDuration(uint256 recycleAfterDuration) 54 | public 55 | { 56 | _recycleAfterDuration = recycleAfterDuration; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /contracts/test/TestERC223Callback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IERC223Token.sol"; 4 | import "../Standards/IERC223Callback.sol"; 5 | 6 | 7 | contract TestERC223Callback is IERC223Callback { 8 | 9 | //////////////////////// 10 | // Mutable state 11 | //////////////////////// 12 | address private _from; 13 | uint256 private _amount; 14 | bytes32 private _dataKeccak; 15 | 16 | 17 | //////////////////////// 18 | // Constructor 19 | //////////////////////// 20 | constructor() public { 21 | // some "random" hash 22 | _dataKeccak = keccak256(abi.encodePacked(address(this))); 23 | } 24 | 25 | //////////////////////// 26 | // Public functions 27 | //////////////////////// 28 | function tokenFallback(address from, uint256 amount, bytes data) 29 | public 30 | { 31 | _from = from; 32 | _amount = amount; 33 | _dataKeccak = keccak256(data); 34 | } 35 | 36 | function amount() public constant returns (uint256) { 37 | return _amount; 38 | } 39 | 40 | function from() public constant returns (address) { 41 | return _from; 42 | } 43 | 44 | function dataKeccak() public constant returns (bytes32) { 45 | return _dataKeccak; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /contracts/test/TestERC223LegacyCallback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IERC223Token.sol"; 4 | import "../Standards/IERC223LegacyCallback.sol"; 5 | 6 | 7 | contract TestERC223LegacyCallback is IERC223LegacyCallback { 8 | 9 | //////////////////////// 10 | // Mutable state 11 | //////////////////////// 12 | address private _from; 13 | uint256 private _amount; 14 | bytes32 private _dataKeccak; 15 | 16 | 17 | //////////////////////// 18 | // Constructor 19 | //////////////////////// 20 | constructor() public { 21 | // some "random" hash 22 | _dataKeccak = keccak256(abi.encodePacked(address(this))); 23 | } 24 | 25 | //////////////////////// 26 | // Public functions 27 | //////////////////////// 28 | function onTokenTransfer( 29 | address from, 30 | uint256 amount, 31 | bytes data 32 | ) 33 | public 34 | { 35 | _from = from; 36 | _amount = amount; 37 | _dataKeccak = keccak256(data); 38 | } 39 | 40 | function amount() public constant returns (uint256) { 41 | return _amount; 42 | } 43 | 44 | function from() public constant returns (address) { 45 | return _from; 46 | } 47 | 48 | function dataKeccak() public constant returns (bytes32) { 49 | return _dataKeccak; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/test/TestERC677Callback.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/IERC677Token.sol"; 4 | import "../Standards/IERC677Callback.sol"; 5 | 6 | 7 | contract TestERC677Callback is IERC677Callback { 8 | 9 | //////////////////////// 10 | // Mutable state 11 | //////////////////////// 12 | bool private _returnOnCallback; 13 | bytes32 private _acceptedExtraData; 14 | 15 | //////////////////////// 16 | // Constructor 17 | //////////////////////// 18 | constructor() public { 19 | _acceptedExtraData = keccak256(""); 20 | } 21 | 22 | //////////////////////// 23 | // Public functions 24 | //////////////////////// 25 | function receiveApproval( 26 | address from, 27 | uint256 amount, 28 | address token, // IERC667Token 29 | bytes data 30 | ) 31 | public 32 | returns (bool) 33 | { 34 | require(token == msg.sender); 35 | require(keccak256(data) == _acceptedExtraData); 36 | bool success = IERC677Token(token).transferFrom(from, address(this), amount); 37 | require(success); 38 | return _returnOnCallback; 39 | } 40 | 41 | function setCallbackReturnValue(bool success) 42 | public 43 | { 44 | _returnOnCallback = success; 45 | } 46 | 47 | function setAcceptedExtraData(bytes acceptedExtraData) 48 | public 49 | { 50 | _acceptedExtraData = keccak256(acceptedExtraData); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /contracts/test/TestIdentityRecord.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Identity/IIdentityRegistry.sol"; 4 | 5 | 6 | contract TestIdentityRecord { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | function getIdentityRecord(bytes32 claims) public pure returns (bool[6] deserializedClaims){ 13 | IdentityRecord.IdentityClaims memory ds = IdentityRecord.deserializeClaims(claims); 14 | assembly { 15 | deserializedClaims := ds 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/test/TestMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Math.sol"; 4 | 5 | 6 | contract TestMath { 7 | 8 | //////////////////////// 9 | // Public functions 10 | //////////////////////// 11 | 12 | function _absDiff(uint256 v1, uint256 v2) 13 | public 14 | pure 15 | returns(uint256) 16 | { 17 | return Math.absDiff(v1, v2); 18 | } 19 | 20 | function _divRound(uint256 v, uint256 d) 21 | public 22 | pure 23 | returns(uint256) 24 | { 25 | 26 | return Math.divRound(v, d); 27 | } 28 | 29 | function _decimalFraction(uint256 amount, uint256 frac) 30 | public 31 | pure 32 | returns(uint256) 33 | { 34 | return Math.decimalFraction(amount, frac); 35 | } 36 | 37 | function _proportion(uint256 amount, uint256 part, uint256 total) 38 | public 39 | pure 40 | returns(uint256) 41 | { 42 | return Math.proportion(amount, part, total); 43 | } 44 | 45 | function _min(uint256 a, uint256 b) 46 | public 47 | pure 48 | returns (uint256) 49 | { 50 | return Math.min(a, b); 51 | } 52 | 53 | function _max(uint256 a, uint256 b) 54 | public 55 | pure 56 | returns (uint256) 57 | { 58 | return Math.max(a, b); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /contracts/test/TestNeumark.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Neumark.sol"; 4 | import "../Standards/IWithdrawableToken.sol"; 5 | 6 | 7 | contract TestNeumark is 8 | Neumark, 9 | IWithdrawableToken 10 | { 11 | 12 | //////////////////////// 13 | // Constructor 14 | //////////////////////// 15 | 16 | constructor( 17 | IAccessPolicy accessPolicy, 18 | IEthereumForkArbiter forkArbiter 19 | ) 20 | Neumark(accessPolicy, forkArbiter) 21 | public 22 | { 23 | } 24 | 25 | //////////////////////// 26 | // Public functions 27 | //////////////////////// 28 | 29 | function deposit(uint256 neumarkUlps) 30 | public 31 | { 32 | mGenerateTokens(msg.sender, neumarkUlps); 33 | } 34 | 35 | function withdraw(uint256 amount) 36 | public 37 | { 38 | mDestroyTokens(msg.sender, amount); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /contracts/test/TestNullContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract TestNullContract { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /contracts/test/TestReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | import "../Standards/IERC223Callback.sol"; 5 | import "../Standards/IERC223LegacyCallback.sol"; 6 | 7 | /** contract to be used in frontend testing for receiving of 8 | - ether 9 | - ERC223 tokens 10 | - tokens with legacy ERC223 tokenFallback (e.g. Neumark.sol) 11 | */ 12 | contract TestReceiver is IERC223Callback, IERC223LegacyCallback { 13 | 14 | //////////////////////// 15 | // Mutable state 16 | //////////////////////// 17 | address private _from; 18 | uint256 private _amount; 19 | bytes32 private _dataKeccak; 20 | bool private _acceptERC223; 21 | 22 | //////////////////////// 23 | // Constructor 24 | //////////////////////// 25 | constructor() public { 26 | // some "random" hash 27 | _dataKeccak = keccak256(abi.encodePacked(address(this))); 28 | _acceptERC223 = true; 29 | } 30 | 31 | 32 | //////////////////////// 33 | // Public functions 34 | //////////////////////// 35 | function setERC223Acceptance(bool acceptERC223) public { 36 | _acceptERC223 = acceptERC223; 37 | } 38 | 39 | // fallback function to receive ether 40 | function () external payable {} 41 | 42 | // fallback function to receive ERC223-Tokens 43 | function tokenFallback(address from, uint256 amount, bytes data) 44 | public 45 | { 46 | require(_acceptERC223, "Token fallback is not enabled"); 47 | _from = from; 48 | _amount = amount; 49 | _dataKeccak = keccak256(data); 50 | } 51 | 52 | // fallback function to support legacy ERC223 Fallback 53 | function onTokenTransfer(address from, uint256 amount, bytes data) 54 | public 55 | { 56 | require(_acceptERC223, "Legacy token fallback is not enabled."); 57 | _from = from; 58 | _amount = amount; 59 | _dataKeccak = keccak256(data); 60 | } 61 | 62 | function amount() public constant returns (uint256) { 63 | return _amount; 64 | } 65 | 66 | function from() public constant returns (address) { 67 | return _from; 68 | } 69 | 70 | function dataKeccak() public constant returns (bytes32) { 71 | return _dataKeccak; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /contracts/test/TestReclaimable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../AccessControl/AccessControlled.sol"; 4 | import "../Reclaimable.sol"; 5 | 6 | 7 | contract TestReclaimable is 8 | AccessControlled, 9 | Reclaimable 10 | { 11 | //////////////////////// 12 | // Constructor 13 | //////////////////////// 14 | 15 | constructor(IAccessPolicy accessPolicy) 16 | AccessControlled(accessPolicy) 17 | Reclaimable() 18 | public 19 | { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/test/TestSender.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | /** Contract that will send all its ether to a given address, reverts upon failure */ 4 | contract TestSender { 5 | function sendAllEther(address to) public { 6 | to.transfer(address(this).balance); 7 | } 8 | 9 | // fallback function to receive ether 10 | function () external payable {} 11 | } 12 | -------------------------------------------------------------------------------- /contracts/test/TestSnapshot.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Snapshot/Snapshot.sol"; 4 | import "../Snapshot/DailyAndSnapshotable.sol"; 5 | 6 | 7 | contract TestSnapshot is 8 | Snapshot, 9 | DailyAndSnapshotable 10 | { 11 | //////////////////////// 12 | // Mutable state 13 | //////////////////////// 14 | 15 | Values[] private _val; 16 | 17 | //////////////////////// 18 | // Constructor 19 | //////////////////////// 20 | constructor(uint256 start) 21 | DailyAndSnapshotable(start) 22 | public 23 | {} 24 | 25 | //////////////////////// 26 | // Public functions 27 | ////////////////////////} 28 | 29 | function setValue(uint256 x) 30 | public 31 | { 32 | setValue(_val, x); 33 | } 34 | 35 | function hasValue() 36 | public 37 | constant 38 | returns (bool) 39 | { 40 | return hasValue(_val); 41 | } 42 | 43 | function getValue(uint256 def) 44 | public 45 | constant 46 | returns (uint256) 47 | { 48 | return getValue(_val, def); 49 | } 50 | 51 | function hasValueAt(uint256 snapshot) 52 | public 53 | constant 54 | returns (bool) 55 | { 56 | return hasValueAt(_val, snapshot); 57 | } 58 | 59 | function getValueAt(uint256 snapshot, uint256 def) 60 | public 61 | constant 62 | returns (uint256) 63 | { 64 | return getValueAt(_val, snapshot, def); 65 | } 66 | 67 | // 68 | // Implements ISnapshotable 69 | // 70 | 71 | /// upper bound of series snapshotIds for which there's a value 72 | function currentSnapshotId() 73 | public 74 | constant 75 | returns (uint256) 76 | { 77 | return mCurrentSnapshotId(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /contracts/test/TestToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../SnapshotToken/StandardToken.sol"; 4 | import "../SnapshotToken/Helpers/TrustlessTokenController.sol"; 5 | 6 | 7 | contract TestToken is 8 | StandardToken, 9 | TrustlessTokenController 10 | { 11 | 12 | //////////////////////// 13 | // Constructor 14 | //////////////////////// 15 | 16 | constructor(uint256 initialBalance) 17 | StandardToken() 18 | public 19 | { 20 | _balances[msg.sender] = initialBalance; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/test/TestTokenControllerPassThrough.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../Standards/ITokenController.sol"; 4 | 5 | 6 | contract TestTokenControllerPassThrough is ITokenController 7 | { 8 | 9 | //////////////////////// 10 | // Public Functions 11 | //////////////////////// 12 | 13 | // 14 | // Implements ITokenController 15 | // 16 | 17 | function onTransfer(address, address, address ,uint256) 18 | public 19 | constant 20 | returns (bool allow) 21 | { 22 | return true; 23 | } 24 | 25 | /// always approve 26 | function onApprove(address, address, uint256) 27 | public 28 | constant 29 | returns (bool allow) 30 | { 31 | return true; 32 | } 33 | 34 | function onAllowance(address /*owner*/, address /*spender*/) 35 | public 36 | constant 37 | returns (uint256) 38 | { 39 | return 0; 40 | } 41 | 42 | function onGenerateTokens(address, address, uint256) 43 | public 44 | constant 45 | returns (bool allow) 46 | { 47 | return true; 48 | } 49 | 50 | function onDestroyTokens(address, address, uint256) 51 | public 52 | constant 53 | returns (bool allow) 54 | { 55 | return true; 56 | } 57 | 58 | function onChangeTokenController(address /*sender*/, address /*newController*/) 59 | public 60 | constant 61 | returns (bool) 62 | { 63 | return true; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /contracts/test/TestUpdatedIdentityRecord.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | 4 | contract TestUpdatedIdentityRecord { 5 | 6 | //////////////////////// 7 | // Public functions 8 | //////////////////////// 9 | struct IdentityClaimsV2 { 10 | bool isVerified; // 1 bit 11 | bool isSophisticatedInvestor; // 1 bit 12 | bool hasBankAccount; // 1 bit 13 | bool accountFrozen; // 1 bit 14 | bool requiresRegDAccreditation; // 1 bit 15 | bool hasValidRegDAccreditation; // 1 bit 16 | bool newProperty; // this is a new property to test the extension of the identity claims 17 | } 18 | 19 | function deserializeClaimsV2(bytes32 data) internal pure returns (IdentityClaimsV2 memory claims) { 20 | assembly { 21 | mstore(claims, and(data, 0x1)) 22 | mstore(add(claims, 0x20), div(and(data, 0x2), 0x2)) 23 | mstore(add(claims, 0x40), div(and(data, 0x4), 0x4)) 24 | mstore(add(claims, 0x60), div(and(data, 0x8), 0x8)) 25 | mstore(add(claims, 0x80), div(and(data, 0x10), 0x10)) 26 | mstore(add(claims, 0xA0), div(and(data, 0x20), 0x20)) 27 | mstore(add(claims, 0xC0), div(and(data, 0x40), 0x40)) 28 | } 29 | } 30 | 31 | function getIdentityRecord(bytes32 claims) public pure returns (bool[7] deserializedClaims){ 32 | IdentityClaimsV2 memory ds = deserializeClaimsV2(claims); 33 | assembly { 34 | deserializedClaims := ds 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/test/TestVotingController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.26; 2 | 3 | import "../VotingCenter/IVotingController.sol"; 4 | import "../Universe.sol"; 5 | import "../KnownContracts.sol"; 6 | 7 | 8 | contract TestVotingController is IVotingController, KnownContracts { 9 | 10 | //////////////////////// 11 | // Constructor 12 | //////////////////////// 13 | constructor(Universe /*universe*/) 14 | public 15 | {} 16 | 17 | // 18 | // Implementation of IVotingController 19 | // 20 | 21 | function onAddProposal(bytes32 /*proposalId*/, address /*initiator*/, address /*token*/) 22 | public 23 | constant 24 | returns (bool) 25 | { 26 | return true; 27 | } 28 | 29 | function onChangeVotingController(address /*sender*/, IVotingController /*newController*/) 30 | public 31 | constant 32 | returns (bool) 33 | { 34 | return true; 35 | } 36 | 37 | // 38 | // Implementation of IContractId 39 | // 40 | 41 | function contractId() public pure returns (bytes32 id, uint256 version) { 42 | return (VOTING_CONTROLLER, 0); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /doc/NEUcurveTestPoints.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/doc/NEUcurveTestPoints.pdf -------------------------------------------------------------------------------- /doc/agreementparity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/doc/agreementparity.png -------------------------------------------------------------------------------- /doc/icbmcontracts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/doc/icbmcontracts.png -------------------------------------------------------------------------------- /legal/NEUMARK TOKEN HOLDER AGREEMENT.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/legal/NEUMARK TOKEN HOLDER AGREEMENT.docx -------------------------------------------------------------------------------- /legal/RESERVATION AGREEMENT.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neufund/platform-contracts/9f83fd6a544faa575b1fc58502247b2df559283b/legal/RESERVATION AGREEMENT.docx -------------------------------------------------------------------------------- /migrations/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": ["off"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /migrations/102_fixtures_kyc.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getFixtureAccounts = require("./fixtures/accounts").getFixtureAccounts; 4 | const getDeployerAccount = require("./config").getDeployerAccount; 5 | const toBytes32 = require("../test/helpers/utils").toBytes32; 6 | const serializeClaims = require("../test/helpers/identityClaims").serializeClaims; 7 | 8 | module.exports = function deployContracts(deployer, network, accounts) { 9 | const CONFIG = getConfig(web3, network, accounts); 10 | if (CONFIG.shouldSkipStep(__filename)) return; 11 | if (CONFIG.isLiveDeployment) return; 12 | 13 | const DEPLOYER = getDeployerAccount(network, accounts); 14 | const Universe = artifacts.require(CONFIG.artifacts.UNIVERSE); 15 | const IdentityRegistry = artifacts.require(CONFIG.artifacts.IDENTITY_REGISTRY); 16 | deployer.then(async () => { 17 | const fas = getFixtureAccounts(); 18 | 19 | console.log("Add KYC claims to fixtures accounts"); 20 | const requireKyc = Object.keys(fas).filter(fa => fas[fa].identityClaims !== undefined); 21 | 22 | const requireKycAddresses = requireKyc.map(fa => fas[fa].address); 23 | 24 | const zeroClaims = requireKyc.map(() => toBytes32("0x0")); 25 | const verifiedClaims = requireKyc.map(fa => { 26 | const claims = fas[fa].identityClaims; 27 | 28 | return serializeClaims( 29 | claims.isVerified, 30 | claims.isSophisticatedInvestor, 31 | claims.hasBankAccount, 32 | claims.accountFrozen, 33 | ); 34 | }); 35 | 36 | const universe = await Universe.deployed(); 37 | const identityRegistry = await IdentityRegistry.at(await universe.identityRegistry()); 38 | await identityRegistry.setMultipleClaims(requireKycAddresses, zeroClaims, verifiedClaims, { 39 | from: DEPLOYER, 40 | }); 41 | 42 | const claims = await identityRegistry.getClaims(requireKycAddresses[3]); 43 | if (claims !== verifiedClaims[3]) { 44 | throw new Error("claims could not be set"); 45 | } 46 | }); 47 | }; 48 | -------------------------------------------------------------------------------- /migrations/103_ether_token_deposits.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getFixtureAccounts = require("./fixtures/accounts").getFixtureAccounts; 4 | 5 | module.exports = function deployContracts(deployer, network, accounts) { 6 | const CONFIG = getConfig(web3, network, accounts); 7 | if (CONFIG.shouldSkipStep(__filename)) return; 8 | 9 | const EtherToken = artifacts.require(CONFIG.artifacts.ETHER_TOKEN); 10 | const Universe = artifacts.require(CONFIG.artifacts.UNIVERSE); 11 | 12 | deployer.then(async () => { 13 | // skip for pure live deployment 14 | if (CONFIG.isLiveDeployment && !CONFIG.ISOLATED_UNIVERSE) return; 15 | 16 | const universe = await Universe.deployed(); 17 | const etherToken = await EtherToken.at(await universe.etherToken()); 18 | 19 | const fas = getFixtureAccounts(accounts); 20 | console.log("Deposit in EtherToken from fixture accounts"); 21 | 22 | for (const f of Object.keys(fas)) { 23 | if (fas[f].balances && fas[f].balances.etherToken && fas[f].balances.etherToken > 0) { 24 | await etherToken.deposit({ 25 | from: fas[f].address, 26 | value: CONFIG.Q18.mul(fas[f].balances.etherToken), 27 | }); 28 | 29 | const balance = await etherToken.balanceOf(fas[f].address); 30 | console.log(`Account ${f} has ${balance.div(CONFIG.Q18).toString()} ETH-T.`); 31 | } 32 | } 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /migrations/104_euro_token_deposits.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getFixtureAccounts = require("./fixtures/accounts").getFixtureAccounts; 4 | const getDeployerAccount = require("./config").getDeployerAccount; 5 | 6 | module.exports = function deployContracts(deployer, network, accounts) { 7 | const CONFIG = getConfig(web3, network, accounts); 8 | if (CONFIG.shouldSkipStep(__filename)) return; 9 | 10 | const DEPLOYER = getDeployerAccount(network, accounts); 11 | 12 | const EuroToken = artifacts.require(CONFIG.artifacts.EURO_TOKEN); 13 | const Universe = artifacts.require(CONFIG.artifacts.UNIVERSE); 14 | 15 | deployer.then(async () => { 16 | // skip for pure live deployment 17 | if (CONFIG.isLiveDeployment && !CONFIG.ISOLATED_UNIVERSE) return; 18 | 19 | const universe = await Universe.deployed(); 20 | const euroToken = await EuroToken.at(await universe.euroToken()); 21 | 22 | const fas = getFixtureAccounts(accounts); 23 | 24 | console.log("Deposit in EuroToken from fixture accounts"); 25 | for (const f of Object.keys(fas)) { 26 | if (fas[f].balances && fas[f].balances.euroToken && fas[f].balances.euroToken > 0) { 27 | await euroToken.deposit(fas[f].address, CONFIG.Q18.mul(fas[f].balances.euroToken), "0x0", { 28 | from: DEPLOYER, 29 | }); 30 | 31 | const balance = await euroToken.balanceOf(fas[f].address); 32 | console.log(`Account ${f} has ${balance.div(CONFIG.Q18).toString()} EUR-T.`); 33 | } 34 | } 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /migrations/13_deploy_eto_terms_constraints.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getDeployerAccount = require("./config").getDeployerAccount; 4 | const initializeMigrationStep = require("./helpers").initializeMigrationStep; 5 | const deployConstraints = require("./deployConstraints").deployConstraints; 6 | const knownInterfaces = require("../test/helpers/knownInterfaces").knownInterfaces; 7 | 8 | module.exports = function deployContracts(deployer, network, accounts) { 9 | const CONFIG = getConfig(web3, network, accounts); 10 | if (CONFIG.shouldSkipStep(__filename)) return; 11 | 12 | const PlatformTerms = artifacts.require(CONFIG.artifacts.PLATFORM_TERMS); 13 | 14 | deployer.then(async () => { 15 | const universe = await initializeMigrationStep(CONFIG, artifacts, web3); 16 | // deploy first package of constraints 17 | const deployerAddress = getDeployerAccount(network, accounts); 18 | await deployConstraints(CONFIG, artifacts, deployer, deployerAddress, universe, 1); 19 | 20 | if (CONFIG.isLiveDeployment) { 21 | console.log("re-deploying PlatformTerms on live network"); 22 | await deployer.deploy(PlatformTerms); 23 | const platformTerms = await PlatformTerms.deployed(); 24 | await universe.setSingleton(knownInterfaces.platformTerms, platformTerms.address); 25 | } 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /migrations/14_new_disbursal_controller_for_eto_recycle.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getDeployerAccount = require("./config").getDeployerAccount; 4 | const initializeMigrationStep = require("./helpers").initializeMigrationStep; 5 | const createAccessPolicy = require("../test/helpers/createAccessPolicy").default; 6 | const { TriState } = require("../test/helpers/triState"); 7 | const roles = require("../test/helpers/roles").default; 8 | 9 | module.exports = function deployContracts(deployer, network, accounts) { 10 | const CONFIG = getConfig(web3, network, accounts); 11 | if (CONFIG.shouldSkipStep(__filename)) return; 12 | 13 | const RoleBasedAccessPolicy = artifacts.require(CONFIG.artifacts.ROLE_BASED_ACCESS_POLICY); 14 | const FeeDisbursal = artifacts.require(CONFIG.artifacts.FEE_DISBURSAL); 15 | const FeeDisbursalController = artifacts.require(CONFIG.artifacts.FEE_DISBURSAL_CONTROLLER); 16 | const DEPLOYER = getDeployerAccount(network, accounts); 17 | 18 | deployer.then(async () => { 19 | const universe = await initializeMigrationStep(CONFIG, artifacts, web3); 20 | console.log("Temporary permission for ROLE_DISBURSAL_MANAGER"); 21 | const accessPolicy = await RoleBasedAccessPolicy.at(await universe.accessPolicy()); 22 | const feeDisbursalAddress = await universe.feeDisbursal(); 23 | await createAccessPolicy(accessPolicy, [ 24 | // temporary disbursal manager to change controller, will be dropped in finalize 25 | { 26 | subject: DEPLOYER, 27 | role: roles.disbursalManager, 28 | state: TriState.Allow, 29 | }, 30 | ]); 31 | console.log("Deploying FeeDisbursalController"); 32 | await deployer.deploy(FeeDisbursalController, universe.address); 33 | const controller = await FeeDisbursalController.deployed(); 34 | console.log("Changing fee disbursal controller"); 35 | const feeDisbursal = await FeeDisbursal.at(feeDisbursalAddress); 36 | await feeDisbursal.changeFeeDisbursalController(controller.address); 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /migrations/15_deploy_sme_eto_li_constraints.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getDeployerAccount = require("./config").getDeployerAccount; 4 | const initializeMigrationStep = require("./helpers").initializeMigrationStep; 5 | const deployConstraints = require("./deployConstraints").deployConstraints; 6 | 7 | module.exports = function deployContracts(deployer, network, accounts) { 8 | const CONFIG = getConfig(web3, network, accounts); 9 | if (CONFIG.shouldSkipStep(__filename)) return; 10 | 11 | deployer.then(async () => { 12 | const universe = await initializeMigrationStep(CONFIG, artifacts, web3); 13 | // deploy first package of constraints 14 | const deployerAddress = getDeployerAccount(network, accounts); 15 | await deployConstraints(CONFIG, artifacts, deployer, deployerAddress, universe, 2); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /migrations/16_deploy_voting_center.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getDeployerAccount = require("./config").getDeployerAccount; 4 | const initializeMigrationStep = require("./helpers").initializeMigrationStep; 5 | const createAccessPolicy = require("../test/helpers/createAccessPolicy").default; 6 | const knownInterfaces = require("../test/helpers/knownInterfaces").knownInterfaces; 7 | const { TriState } = require("../test/helpers/triState"); 8 | const roles = require("../test/helpers/roles").default; 9 | 10 | module.exports = function deployContracts(deployer, network, accounts) { 11 | const CONFIG = getConfig(web3, network, accounts); 12 | if (CONFIG.shouldSkipStep(__filename)) return; 13 | 14 | const RoleBasedAccessPolicy = artifacts.require(CONFIG.artifacts.ROLE_BASED_ACCESS_POLICY); 15 | const VotingCenter = artifacts.require(CONFIG.artifacts.VOTING_CENTER); 16 | const VotingController = artifacts.require(CONFIG.artifacts.VOTING_CENTER_CONTROLLER); 17 | const DEPLOYER = getDeployerAccount(network, accounts); 18 | 19 | deployer.then(async () => { 20 | const universe = await initializeMigrationStep(CONFIG, artifacts, web3); 21 | // deploy fee disbursal and controller 22 | console.log("Deploying VotingController"); 23 | await deployer.deploy(VotingController, universe.address); 24 | const controller = await VotingController.deployed(); 25 | console.log("Deploying VotingCenter"); 26 | await deployer.deploy(VotingCenter, controller.address); 27 | const votingCenter = await VotingCenter.deployed(); 28 | 29 | const accessPolicy = await RoleBasedAccessPolicy.at(await universe.accessPolicy()); 30 | await createAccessPolicy(accessPolicy, [ 31 | // temporary access to universe, will be dropped in finalize 32 | { 33 | subject: DEPLOYER, 34 | role: roles.universeManager, 35 | state: TriState.Allow, 36 | }, 37 | ]); 38 | 39 | console.log("Setting singletons"); 40 | await universe.setSingleton(knownInterfaces.votingCenter, votingCenter.address); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /migrations/198_save_eto_constrains_fixtures_state.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const fs = require("fs"); 3 | const getConfig = require("./config").getConfig; 4 | const { join } = require("path"); 5 | const describedConstraints = require("./fixtures/eto_terms_constraints").describedConstraints; 6 | 7 | module.exports = function deployContracts(deployer, network, accounts) { 8 | const CONFIG = getConfig(web3, network, accounts); 9 | if (CONFIG.shouldSkipStep(__filename)) return; 10 | if (CONFIG.isLiveDeployment) return; 11 | 12 | deployer.then(async () => { 13 | const etoConstraintsFixturesPath = join( 14 | __dirname, 15 | "../build/eto_terms_constraints_fixtures.json", 16 | ); 17 | fs.writeFile(etoConstraintsFixturesPath, JSON.stringify(describedConstraints, null, 2), err => { 18 | if (err) throw new Error(err); 19 | }); 20 | console.log(`ETO constraints described in ${etoConstraintsFixturesPath}`); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | 3 | module.exports = function deployMigration(_) { 4 | // we do not deploy migrations anymore 5 | // left fro compatibility 6 | }; 7 | -------------------------------------------------------------------------------- /migrations/4_link_contracts.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const { TriState, GLOBAL } = require("../test/helpers/triState"); 4 | const getDeployerAccount = require("./config").getDeployerAccount; 5 | const roles = require("../test/helpers/roles").default; 6 | 7 | module.exports = function deployContracts(deployer, network, accounts) { 8 | const CONFIG = getConfig(web3, network, accounts); 9 | if (CONFIG.shouldSkipStep(__filename)) return; 10 | 11 | const DEPLOYER = getDeployerAccount(network, accounts); 12 | const RoleBasedAccessPolicy = artifacts.require(CONFIG.artifacts.ROLE_BASED_ACCESS_POLICY); 13 | const ICBMLockedAccount = artifacts.require(CONFIG.artifacts.ICBM_LOCKED_ACCOUNT); 14 | const Commitment = artifacts.require(CONFIG.artifacts.ICBM_COMMITMENT); 15 | 16 | deployer.then(async () => { 17 | const accessPolicy = await RoleBasedAccessPolicy.deployed(); 18 | const commitment = await Commitment.deployed(); 19 | const etherLock = await ICBMLockedAccount.at(await commitment.etherLock()); 20 | const euroLock = await ICBMLockedAccount.at(await commitment.euroLock()); 21 | 22 | // locked account admin role to yourself during deployment and relinquish control later 23 | await accessPolicy.setUserRole(DEPLOYER, roles.lockedAccountAdmin, GLOBAL, TriState.Allow); 24 | 25 | console.log("Attaching Commitment to LockedAccounts"); 26 | await euroLock.setController(commitment.address); 27 | await etherLock.setController(commitment.address); 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /migrations/5_amend_agreements.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | 4 | module.exports = function deployContracts(deployer, network, accounts) { 5 | const CONFIG = getConfig(web3, network, accounts); 6 | if (CONFIG.shouldSkipStep(__filename)) return; 7 | 8 | const Neumark = artifacts.require(CONFIG.artifacts.NEUMARK); 9 | const Commitment = artifacts.require(CONFIG.artifacts.ICBM_COMMITMENT); 10 | 11 | if (CONFIG.isLiveDeployment) { 12 | console.log("---------------------------------------------"); 13 | console.log( 14 | // eslint-disable-next-line max-len 15 | `Must use ${CONFIG.addresses.PLATFORM_OPERATOR_REPRESENTATIVE} account to deploy agreements on live network`, 16 | ); 17 | console.log("---------------------------------------------"); 18 | return; 19 | } 20 | 21 | deployer.then(async () => { 22 | const neumark = await Neumark.deployed(); 23 | const commitment = await Commitment.deployed(); 24 | 25 | console.log("Amending agreements"); 26 | await neumark.amendAgreement(CONFIG.NEUMARK_HOLDER_AGREEMENT, { 27 | from: CONFIG.addresses.PLATFORM_OPERATOR_REPRESENTATIVE, 28 | }); 29 | await commitment.amendAgreement(CONFIG.RESERVATION_AGREEMENT, { 30 | from: CONFIG.addresses.PLATFORM_OPERATOR_REPRESENTATIVE, 31 | }); 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /migrations/7_distribute_ether_to_fixtures_accounts.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getFixtureAccounts = require("./fixtures/accounts").getFixtureAccounts; 4 | const getDeployerAccount = require("./config").getDeployerAccount; 5 | const promisify = require("../test/helpers/utils").promisify; 6 | 7 | module.exports = function deployContracts(deployer, network, accounts) { 8 | const CONFIG = getConfig(web3, network, accounts); 9 | if (CONFIG.shouldSkipStep(__filename)) return; 10 | if (CONFIG.isLiveDeployment) return; 11 | 12 | const DEPLOYER = getDeployerAccount(network, accounts); 13 | deployer.then(async () => { 14 | const fas = getFixtureAccounts(); 15 | 16 | console.log("Distribute ether to fixtures accounts"); 17 | for (const f of Object.keys(fas)) { 18 | let initialEthBalance = 1000; 19 | if (fas[f].balances && fas[f].balances.initialEth !== undefined) { 20 | initialEthBalance = fas[f].balances.initialEth; 21 | } 22 | 23 | const valueToSend = web3.toWei(initialEthBalance, "ether"); 24 | 25 | await promisify(web3.eth.sendTransaction)({ 26 | from: DEPLOYER, 27 | to: fas[f].address, 28 | value: valueToSend, 29 | gasPrice: 100, 30 | gas: 21000, 31 | }); 32 | 33 | const etherBalance = await promisify(web3.eth.getBalance)(fas[f].address); 34 | if ( 35 | fas[f].balances && 36 | fas[f].balances.initialEth && 37 | etherBalance.lt(fas[f].balances.initialEth) 38 | ) { 39 | throw new Error(`Account ${f} has too low initial ETH balance`); 40 | } 41 | 42 | console.log(`${f} has initial ${etherBalance.div(CONFIG.Q18)} ETH`); 43 | } 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /migrations/8_patch_icbm_state.js: -------------------------------------------------------------------------------- 1 | require("babel-register"); 2 | const getConfig = require("./config").getConfig; 3 | const getFixtureAccounts = require("./fixtures/accounts").getFixtureAccounts; 4 | 5 | module.exports = function deployContracts(deployer, network, accounts) { 6 | const CONFIG = getConfig(web3, network, accounts); 7 | if (CONFIG.shouldSkipStep(__filename)) return; 8 | // skip fixtures on live deployment 9 | if (CONFIG.isLiveDeployment) return; 10 | 11 | const fas = getFixtureAccounts(accounts); 12 | const Commitment = artifacts.require(CONFIG.artifacts.ICBM_COMMITMENT); 13 | const ICBMEuroToken = artifacts.require(CONFIG.artifacts.ICBM_EURO_TOKEN); 14 | 15 | async function commitDuringIcbm(fixtures, commitment, euroToken) { 16 | for (const [fixtureName, fixtureDefinition] of Object.entries(fixtures)) { 17 | if (fixtureDefinition && fixtureDefinition.icbmCommitment) { 18 | const { 19 | icbmCommitment: { ETH: ethCommitment, EUR: eurCommitment }, 20 | } = fixtureDefinition || {}; 21 | if (ethCommitment) { 22 | console.log(`Account ${fixtureName} commits ${ethCommitment} ETH during ICBM`); 23 | await commitment.commit({ 24 | from: fixtureDefinition.address, 25 | value: CONFIG.Q18.mul(ethCommitment), 26 | }); 27 | } 28 | if (eurCommitment) { 29 | console.log(`Account ${fixtureName} commits ${eurCommitment} EUR during ICBM`); 30 | const amountEur = CONFIG.Q18.mul(eurCommitment); 31 | await euroToken.deposit(fixtureDefinition.address, amountEur); 32 | await euroToken.approve(commitment.address, amountEur, { 33 | from: fixtureDefinition.address, 34 | }); 35 | await commitment.commitEuro({ from: fixtureDefinition.address }); 36 | } 37 | } 38 | } 39 | } 40 | 41 | deployer.then(async () => { 42 | const commitment = await Commitment.deployed(); 43 | const euroToken = await ICBMEuroToken.deployed(); 44 | console.log("set Commitment to public phase"); 45 | await commitment._mockTransitionTo(1); 46 | await commitment._mockTransitionTo(2); 47 | console.log("Simulate commitment during ICBM"); 48 | await commitDuringIcbm(fas, commitment, euroToken); 49 | console.log("set Commitment to final phase"); 50 | await commitment._mockTransitionTo(3); 51 | }); 52 | }; 53 | -------------------------------------------------------------------------------- /migrations/fixtures/accounts.js: -------------------------------------------------------------------------------- 1 | import fromPairs from "lodash"; 2 | 3 | const fs = require("fs"); 4 | 5 | const fixturesDataPath = `${__dirname}/accounts.json`; 6 | const accounts = JSON.parse(fs.readFileSync(fixturesDataPath)); 7 | 8 | const createFixtures = () => { 9 | const standardInvestorWithKyc = { 10 | balances: { 11 | etherToken: 0, 12 | euroToken: 745000, 13 | initialEth: 543, 14 | }, 15 | etoParticipations: { 16 | whitelist: { 17 | ETOInPublicState: { discount: 0.5, discountAmount: 10000 }, 18 | }, 19 | presale: { ETOInPublicState: { ETH: { wallet: 28.18 } } }, 20 | sale: { ETOInPayoutState: { ETH: { wallet: 128.17 }, EUR: { wallet: 15000 } } }, 21 | claim: ["ETOInPayoutState"], 22 | }, 23 | }; 24 | 25 | const standardInvestorNoKyc = { 26 | balances: { 27 | initialEth: 100, 28 | }, 29 | }; 30 | 31 | // now when I look at this I think loop would be better... 32 | const fixtures = Object.assign( 33 | accounts, 34 | fromPairs( 35 | Object.keys(accounts) 36 | .filter(a => a.startsWith("demoinvestor") && accounts[a].identityClaims.isVerified) 37 | .map(a => [a, Object.assign(accounts[a], standardInvestorWithKyc)]), 38 | ), 39 | fromPairs( 40 | Object.keys(accounts) 41 | .filter(a => a.startsWith("demoinvestor") && !accounts[a].identityClaims.isVerified) 42 | .map(a => [a, Object.assign(accounts[a], standardInvestorNoKyc)]), 43 | ), 44 | ); 45 | 46 | // lodash apparently added this 47 | delete fixtures.__wrapped__; 48 | delete fixtures.__chain__; 49 | delete fixtures.__actions__; 50 | delete fixtures.__index__; 51 | delete fixtures.__values__; 52 | 53 | return fixtures; 54 | }; 55 | 56 | const fixtures = createFixtures(); 57 | 58 | export function getFixtureAccounts() { 59 | return fixtures; 60 | } 61 | -------------------------------------------------------------------------------- /migrations/fixtures/etos.js: -------------------------------------------------------------------------------- 1 | const { 2 | defEtoTerms, 3 | hnwiEtoDeSecurityTerms, 4 | retailEtoDeVmaTerms, 5 | retailEtoDeVmaTermsTransferable, 6 | miniEtoLiTerms, 7 | miniEtoLiNominalValueTerms, 8 | hnwiEtoLiSecurityTerms, 9 | retailSMEEtoLi, 10 | } = require("./eto_terms"); 11 | const CommitmentState = require("../../test/helpers/commitmentState").CommitmentState; 12 | 13 | const getFixtureAccounts = require("./accounts").getFixtureAccounts; 14 | 15 | const fas = getFixtureAccounts(); 16 | 17 | export const etoFixtures = { 18 | ETONoStartDate: { 19 | state: null, 20 | issuer: fas.ISSUER_SETUP_NO_ST, 21 | terms: hnwiEtoLiSecurityTerms, 22 | }, 23 | 24 | ETOInSetupState: { 25 | state: CommitmentState.Setup, 26 | issuer: fas.ISSUER_SETUP, 27 | terms: defEtoTerms, 28 | }, 29 | 30 | ETOInWhitelistState: { 31 | state: CommitmentState.Whitelist, 32 | issuer: fas.ISSUER_WHITELIST, 33 | terms: hnwiEtoDeSecurityTerms, 34 | }, 35 | 36 | ETOInPublicState: { 37 | state: CommitmentState.Public, 38 | issuer: fas.ISSUER_PUBLIC, 39 | terms: miniEtoLiTerms, 40 | }, 41 | 42 | ETOInSigningState: { 43 | state: CommitmentState.Signing, 44 | issuer: fas.ISSUER_SIGNING, 45 | terms: retailSMEEtoLi, 46 | }, 47 | 48 | ETOInClaimState: { 49 | state: CommitmentState.Claim, 50 | issuer: fas.ISSUER_CLAIMS, 51 | terms: miniEtoLiNominalValueTerms, 52 | }, 53 | 54 | ETOInPayoutState: { 55 | state: CommitmentState.Payout, 56 | issuer: fas.ISSUER_PAYOUT, 57 | terms: retailEtoDeVmaTerms, 58 | }, 59 | 60 | ETOInPayoutStateWithExitContract: { 61 | state: CommitmentState.Payout, 62 | issuer: fas.ISSUER_EXIT, 63 | terms: retailEtoDeVmaTermsTransferable, 64 | exit: "11000000", // 11 mio 65 | }, 66 | 67 | ETOInRefundState: { 68 | state: CommitmentState.Refund, 69 | issuer: fas.ISSUER_REFUND, 70 | terms: defEtoTerms, 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /migrations/migrateController.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | 3 | const knownModules = [ 4 | "0xd8b228c791b70f75338df4d4d644c638f1a58faec0b2f187daf42fb3722af438,0x41a703b63c912953a0cd27ec13238571806cc14534c4a31a6874db8759b9aa6a,0x156c4a2914517b2fdbf2f694bac9d69e03910b75d3298033e1f4f431b517703d,0x1c7166c78ec7465184d422ad6e22121b4881a63128a89653179065e03625ae87,0x6f34e3bc451d7c62ae86b2e212b7cb207815b826f8de016c0128b0d3762753ae,0xcf797981ed83afa34271d9e461566e1f4faa04577471ac007890d663e1727723", 5 | "0,0,0,0,0,0", 6 | ]; 7 | 8 | const knownModuleNames = [ 9 | "ControllerGovernanceEngineId", 10 | "ControllerGeneralInformationId", 11 | "ControllerGovernanceTokenId", 12 | "ControllerETOId", 13 | "ControllerDividendsId", 14 | "SingleEquityTokenControllerId", 15 | ]; 16 | -------------------------------------------------------------------------------- /mocha.js: -------------------------------------------------------------------------------- 1 | import chai from "chai"; 2 | import chaiAsPromised from "chai-as-promised"; 3 | import chaiBignumber from "chai-bignumber"; 4 | 5 | import chaiWeb3 from "./test/helpers/chaiWeb3"; 6 | 7 | chai 8 | .use(chaiAsPromised) 9 | .use(chaiBignumber(web3.BigNumber)) 10 | .use(chaiWeb3); 11 | -------------------------------------------------------------------------------- /multiWalletProvider.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | const ProviderEngine = require("web3-provider-engine"); 3 | // eslint-disable-next-line 4 | const Web3Subprovider = require("web3-provider-engine/subproviders/web3.js"); 5 | const HookedWalletEthTxSubprovider = require("web3-provider-engine/subproviders/hooked-wallet-ethtx"); 6 | const Wallet = require("ethereumjs-wallet"); 7 | 8 | const getFixtureAccounts = require("./migrations/fixtures/accounts").getFixtureAccounts; 9 | 10 | const inherits = require("util").inherits; 11 | 12 | // https://github.com/ethereumjs/ethereumjs-wallet/blob/master/src/provider-engine.js 13 | // https://github.com/MetaMask/web3-provider-engine/blob/master/subproviders/hooked-wallet.js 14 | inherits(MultiWalletSubprovider, HookedWalletEthTxSubprovider); 15 | 16 | function MultiWalletSubprovider(wallets, params) { 17 | const opts = params || {}; 18 | 19 | const indexedWallets = wallets.reduce((map, wallet) => { 20 | const address = wallet.getAddressString().toLowerCase(); 21 | 22 | // eslint-disable-next-line 23 | map[address] = wallet.getPrivateKey(); 24 | return map; 25 | }, {}); 26 | 27 | opts.getAccounts = cb => { 28 | cb(null, Object.keys(indexedWallets)); 29 | }; 30 | opts.getPrivateKey = (address, cb) => { 31 | const lowercasedAddress = address.toLowerCase(); 32 | if (!(lowercasedAddress in indexedWallets)) { 33 | cb(new Error(`Account ${lowercasedAddress} not found`)); 34 | } else { 35 | cb(null, indexedWallets[lowercasedAddress]); 36 | } 37 | }; 38 | 39 | MultiWalletSubprovider.super_.call(this, opts); 40 | } 41 | 42 | export function multiWalletProvider(nodeUrl) { 43 | const web3HttpProvider = new Web3.providers.HttpProvider(nodeUrl); 44 | const engine = new ProviderEngine(); 45 | 46 | const fas = getFixtureAccounts(); 47 | const wallets = []; 48 | for (const name of Object.keys(fas)) { 49 | if (fas[name].privateKey !== null) { 50 | const privateKey = Buffer.from(fas[name].privateKey.substr(2), "hex"); 51 | const wallet = new Wallet(privateKey); 52 | wallets.push(wallet); 53 | } 54 | } 55 | 56 | engine.addProvider(new MultiWalletSubprovider(wallets)); 57 | engine.addProvider(new Web3Subprovider(web3HttpProvider)); 58 | engine.start(); 59 | engine.stop(); 60 | 61 | return engine; 62 | } 63 | -------------------------------------------------------------------------------- /nanoWeb3Provider.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | const ProviderEngine = require("web3-provider-engine"); 3 | // eslint-disable-next-line 4 | const LedgerWalletSubproviderFactory = require("ledger-wallet-provider"); 5 | const Web3Subprovider = require("web3-provider-engine/subproviders/web3.js"); 6 | const FilterSubprovider = require("web3-provider-engine/subproviders/filters.js"); 7 | 8 | export function nanoWeb3Provider(providerUrl, nanoPath) { 9 | const web3HttpProvider = new Web3.providers.HttpProvider(providerUrl); 10 | const engine = new ProviderEngine(); 11 | 12 | engine.addProvider(new FilterSubprovider()); 13 | engine.addProvider(LedgerWalletSubproviderFactory.default(new Web3(web3HttpProvider), nanoPath)); 14 | engine.addProvider(new Web3Subprovider(web3HttpProvider)); 15 | 16 | engine.on("block", () => { 17 | // console.log("================================"); 18 | // console.log( 19 | // "BLOCK CHANGED:", 20 | // `#${block.number.toString("hex")}`, 21 | // `0x${block.hash.toString("hex")}` 22 | // ); 23 | // console.log("================================"); 24 | }); 25 | engine.start(); 26 | engine.stop(); 27 | 28 | return engine; 29 | } 30 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -u 5 | 6 | if [ -d ./build ]; then 7 | rm -rf ./build 8 | fi 9 | yarn truffle compile --all 10 | if [ ! -d ./platform-contracts-artifacts/.git ]; then 11 | git clone https://github.com/Neufund/platform-contracts-artifacts.git 12 | else 13 | cd ./platform-contracts-artifacts && git reset --hard origin/master && git pull && cd .. 14 | fi 15 | if [ -d ./platform-contracts-artifacts/build ]; then 16 | rm -r ./platform-contracts-artifacts/build 17 | fi 18 | cp -r ./build ./platform-contracts-artifacts/build 19 | -------------------------------------------------------------------------------- /scripts/cancelTx.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /* eslint-disable no-continue */ 3 | 4 | require("babel-register"); 5 | const promisify = require("../test/helpers/utils").promisify; 6 | const confirm = require("node-ask").confirm; 7 | 8 | module.exports = async function cancelTx() { 9 | const accounts = await promisify(web3.eth.getAccounts)(); 10 | const nonce = await promisify(web3.eth.getTransactionCount)(accounts[0]); 11 | const gasPrice = 20 * 10 ** 9; // 60 gwei 12 | console.log("Will try to cancel tx in pending pool by sending 0 eth to itself"); 13 | console.log( 14 | `from/to ${accounts[0]} with nonce ${nonce} and gas price ${gasPrice / 10 ** 9} gwei`, 15 | ); 16 | if (!(await confirm("Are you sure? [y/n] "))) { 17 | throw new Error("Aborting!"); 18 | } 19 | const tx = await promisify(web3.eth.sendTransaction)({ 20 | from: accounts[0], 21 | to: accounts[0], 22 | gas: 21000, 23 | gasPrice, 24 | value: 0, 25 | nonce, 26 | }); 27 | console.log(`Submitted tx ${tx}`); 28 | }; 29 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -u 5 | 6 | # get network so we can provide deploy artifacts correctly 7 | NETWORK=$1 8 | if [ -z "$NETWORK" ]; then 9 | echo "provide deploy network name as first positional argument" 10 | echo " ie. ./deploy.sh nf_dev" 11 | exit -1 12 | fi 13 | 14 | if [ ! -d ./platform-contracts-artifacts ]; then 15 | git clone https://github.com/Neufund/platform-contracts-artifacts.git 16 | # else 17 | # cd ./platform-contracts-artifacts && git reset --hard origin/master && git pull && cd .. 18 | fi 19 | if [ ! -d ./platform-contracts-artifacts/build ]; then 20 | echo "please provide build artifacts in ./platform-contracts-artifacts/build via build.sh" 21 | fi 22 | if [ -d ./build ]; then 23 | rm -r ./build 24 | fi 25 | # cp -r ./platform-contracts-artifacts/build ./build 26 | yarn truffle deploy --network $NETWORK 27 | # copy deployed artifacts 28 | if [ -d ./platform-contracts-artifacts/$NETWORK ]; then 29 | rm -r ./platform-contracts-artifacts/$NETWORK 30 | fi 31 | cp -r ./build ./platform-contracts-artifacts/$NETWORK 32 | -------------------------------------------------------------------------------- /scripts/deployWhitelist.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | require("babel-register"); 4 | const commandLineArgs = require("command-line-args"); 5 | const deployWhitelist = require("../migrations/deployETO").deployWhitelist; 6 | const getConfig = require("../migrations/config").getConfig; 7 | const d3 = require("d3-dsv"); 8 | const fs = require("fs"); 9 | 10 | module.exports = async function inspectETO() { 11 | const optionDefinitions = [ 12 | { name: "network", type: String }, 13 | { name: "eto", type: String }, 14 | { name: "whitelist", type: String }, 15 | { name: "dry-run", type: Boolean }, 16 | { name: "check-existing", type: Boolean }, 17 | { name: "verbose-rpc", type: Boolean }, 18 | { name: "exec", type: String, multiple: true, defaultOption: true }, 19 | ]; 20 | 21 | let options; 22 | try { 23 | options = commandLineArgs(optionDefinitions); 24 | } catch (e) { 25 | console.log(`Invalid command line: ${e}`); 26 | console.log(`Expected parameters:`); 27 | console.log(optionDefinitions); 28 | console.log("Expected CSV format"); 29 | console.log("Column 1: Name 'address' value: address of the investor"); 30 | console.log( 31 | "Column 2: Name 'fixed slot amount' value: value of fixed slot as number or 0 when not in fixed slot", 32 | ); 33 | console.log( 34 | "Column 3: Name 'discount' value: decimal fraction that represent discount - fraction of full token price. applies only to a fixed slot!", 35 | ); 36 | throw e; 37 | } 38 | 39 | const CONFIG = getConfig(web3, options.network, []); 40 | console.log("Loading CSV file and parsing"); 41 | const parsedCsv = d3.csvParse(fs.readFileSync(options.whitelist, "UTF-8")); 42 | const whitelist = parsedCsv.map(entry => ({ 43 | address: entry.address, 44 | discountAmount: entry["fixed slot amount"], 45 | discount: entry.discount, 46 | })); 47 | console.log(options); 48 | await deployWhitelist( 49 | artifacts, 50 | CONFIG, 51 | options.eto, 52 | whitelist, 53 | options["dry-run"], 54 | options["check-existing"], 55 | ); 56 | }; 57 | -------------------------------------------------------------------------------- /scripts/fixtures/getETOFixtureAddress.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const fs = require("fs"); 4 | 5 | const args = process.argv.slice(2); 6 | const fixturesDataPath = `${__dirname}/../../build/eto_fixtures.json`; 7 | const etos = JSON.parse(fs.readFileSync(fixturesDataPath)); 8 | 9 | const searchArgument = args.find(x => x !== undefined); 10 | 11 | if (searchArgument && Object.prototype.hasOwnProperty.call(etos, searchArgument)) { 12 | console.log(etos[searchArgument]); 13 | } else { 14 | const accountDefinition = Object.entries(etos).find( 15 | ([_, definition]) => definition.name === searchArgument, 16 | ); 17 | console.log(accountDefinition[0]); 18 | } 19 | -------------------------------------------------------------------------------- /scripts/fixtures/getFixture.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const fs = require("fs"); 4 | 5 | const args = process.argv.slice(2); 6 | const fixturesDataPath = `${__dirname}/../../migrations/fixtures/accounts.json`; 7 | const accounts = JSON.parse(fs.readFileSync(fixturesDataPath)); 8 | 9 | const searchArgument = args.find(x => x !== undefined); 10 | 11 | if (searchArgument && Object.prototype.hasOwnProperty.call(accounts, searchArgument)) { 12 | console.log(accounts[searchArgument]); 13 | } else { 14 | const accountDefinition = Object.entries(accounts).find( 15 | ([_, definition]) => definition.address === searchArgument, 16 | ); 17 | console.log(accountDefinition); 18 | } 19 | -------------------------------------------------------------------------------- /scripts/fixtures/listFixtures.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const fs = require("fs"); 4 | 5 | const fixturesDataPath = `${__dirname}/../../migrations/fixtures/accounts.json`; 6 | const accounts = JSON.parse(fs.readFileSync(fixturesDataPath)); 7 | 8 | console.log(accounts); 9 | -------------------------------------------------------------------------------- /scripts/flatten.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Simple script that flattens all smart contracts up for deployment 3 | 4 | #Smart contract paths 5 | path[0]=../contracts/PaymentTokens/EtherToken.sol 6 | path[1]=../contracts/PaymentTokens/EuroToken.sol 7 | path[2]=../contracts/ICBM/LockedAccount.sol 8 | path[3]=../contracts/ETO/ETOCommitment.sol 9 | path[4]=../contracts/Universe.sol 10 | path[5]=../contracts/Identity/IdentityRegistry.sol 11 | path[6]=../contracts/SimpleExchange.sol 12 | path[7]=../contracts/Company/EquityToken.sol 13 | path[8]=../contracts/Company/SingleEquityTokenController.sol 14 | path[9]=../contracts/PaymentTokens/EuroTokenController.sol 15 | path[10]=../contracts/PlatformTerms.sol 16 | 17 | path[11]=../contracts/ETO/ETOTerms.sol 18 | path[12]=../contracts/Company/EquityTokenholderRights.sol 19 | path[13]=../contracts/ETO/ETOTokenTerms.sol 20 | path[14]=../contracts/ETO/ETODurationTerms.sol 21 | path[15]=../contracts/Company/EquityToken.sol 22 | path[16]=../contracts/FeeDisbursal/FeeDisbursal.sol 23 | path[17]=../contracts/FeeDisbursal/FeeDisbursalController.sol 24 | path[18]=../contracts/ETO/ETOTermsConstraints.sol 25 | path[19]=../contracts/VotingCenter/VotingCenter.sol 26 | path[20]=../contracts/VotingCenter/VotingController.sol 27 | 28 | #Output directory 29 | output=./build/flatten 30 | 31 | for i in {19..20} 32 | do 33 | echo Flattening ${path[i]} to $output 34 | yarn truffle-flattener ${path[i]} $output 35 | done 36 | -------------------------------------------------------------------------------- /scripts/getAddressFromLedger.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | /** 3 | * Simple script to get address from ledger using different derivation paths 4 | * usage: yarn ledgeraddresss "44'/60'/0'/1" if you leave it empty you will get default path 5 | */ 6 | // eslint-disable-next-line 7 | const ledger = require("ledgerco"); 8 | 9 | const TIMEOUT = 5 * 1000; 10 | const DEFAULT_PATH = "44'/60'/0'/0/0"; 11 | 12 | const path = process.argv[2] || DEFAULT_PATH; 13 | console.log("checking path:", path); 14 | 15 | ledger.comm_node 16 | .create_async(TIMEOUT) 17 | .then(comm => { 18 | // eslint-disable-next-line new-cap 19 | const eth = new ledger.eth(comm); 20 | return eth 21 | .getAddress_async(path) 22 | .then(result => { 23 | console.log(result); 24 | comm.close_async(); 25 | }) 26 | .catch(err => console.log(err)); 27 | }) 28 | .catch(err => console.log(err)); 29 | -------------------------------------------------------------------------------- /scripts/helpers.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const moment = require("moment"); 4 | const Q18 = require("../test/helpers/constants").Q18; 5 | 6 | export function wrong(s) { 7 | return ["\x1b[31m", s, "\x1b[0m"]; 8 | } 9 | 10 | export function good(s) { 11 | return ["\x1b[32m", s, "\x1b[0m"]; 12 | } 13 | 14 | function formatValue(prop, value) { 15 | if (typeof value === "object" && value.constructor.name.includes("BigNumber")) { 16 | if (value.gte(Q18.div(1000))) { 17 | return `${value.toString(10)} == ${value.div(Q18).toString(10)} * 10**18`; 18 | } else if (prop.endsWith("_DURATION")) { 19 | const duration = moment.duration(value.toNumber() * 1000); 20 | return `${value.toString(10)} = ${duration.humanize()}`; 21 | } 22 | return value.toString(10); 23 | } 24 | return value; 25 | } 26 | 27 | export async function printConstants(contract) { 28 | for (const func of contract.abi) { 29 | if (func.type === "function" && func.constant && func.inputs.length === 0) { 30 | try { 31 | const output = await contract[func.name](); 32 | const displayValue = formatValue(func.name, output); 33 | console.log(`${func.name}:`, ...good(displayValue)); 34 | } catch (e) { 35 | console.log(`${func.name}`, ...wrong(`REVERTED ${e}`)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | export function explainTerms(name, terms) { 42 | console.log(`\n${name}:`); 43 | for (const k of Object.keys(terms)) { 44 | const displayValue = formatValue(k, terms[k]); 45 | console.log(`${k}: ${displayValue}`); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/inspectETO.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | require("babel-register"); 4 | const commandLineArgs = require("command-line-args"); 5 | const checkETO = require("../migrations/deployETO").checkETO; 6 | const getConfig = require("../migrations/config").getConfig; 7 | 8 | module.exports = async function inspectETO() { 9 | const optionDefinitions = [ 10 | { name: "network", type: String }, 11 | { name: "eto", type: String }, 12 | { name: "exec", type: String, multiple: true, defaultOption: true }, 13 | ]; 14 | 15 | let options; 16 | try { 17 | options = commandLineArgs(optionDefinitions); 18 | } catch (e) { 19 | console.log(`Invalid command line: ${e}`); 20 | console.log(`Expected parameters:`); 21 | console.log(optionDefinitions); 22 | throw e; 23 | } 24 | 25 | const CONFIG = getConfig(web3, options.network, []); 26 | await checkETO(artifacts, CONFIG, options.eto, true); 27 | }; 28 | -------------------------------------------------------------------------------- /scripts/investIntoETOCheck.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple script used in testing of investIntoETO script. It will check if account used by test invested into ETO 3 | */ 4 | 5 | /* eslint-disable no-console */ 6 | require("babel-register"); 7 | const commandLineArgs = require("command-line-args"); 8 | const getConfig = require("../migrations/config").getConfig; 9 | // eslint-disable-next-line 10 | const Accounts = require("web3-eth-accounts"); 11 | 12 | module.exports = async function investIntoETOCheck() { 13 | const optionDefinitions = [ 14 | { name: "network", type: String }, 15 | { name: "pk", type: String }, 16 | { name: "eto", type: String }, 17 | { name: "amount", type: Number }, 18 | ]; 19 | 20 | const options = commandLineArgs(optionDefinitions, { partial: true }); 21 | const valid = options.network && options.pk && options.eto; 22 | if (!valid) { 23 | throw new Error("You didn't provide every one of required parameters: network, pk, eto"); 24 | } 25 | 26 | const address = Accounts.prototype.privateKeyToAccount(options.pk).address; 27 | console.log("Checking if investIntoETO script worked and investment has been made"); 28 | console.log(`Resolved PK to ${address}`); 29 | 30 | const CONFIG = getConfig(web3, options.network, []); 31 | const eto = await artifacts.require(CONFIG.artifacts.STANDARD_ETO_COMMITMENT).at(options.eto); 32 | const ticket = await eto.investorTicket(address); 33 | if (!ticket[6].eq(web3.toWei(options.amount, "ether"))) { 34 | console.log( 35 | `Incorrect amount invested into eto ${options.eto} by user ${address}. It suppose to invest ${ 36 | options.amount 37 | } ETH, but invested ${web3.fromWei(ticket[6], "ether")}.`, 38 | ); 39 | process.exit(1); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /scripts/investIntoETOPrepare.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple script used in testing of investIntoETO script. It will prepare account used by test by setting claims of provided account to verified and will transfer some ETH from Deployer account into provided one. 3 | */ 4 | 5 | /* eslint-disable no-console */ 6 | require("babel-register"); 7 | const commandLineArgs = require("command-line-args"); 8 | const getConfig = require("../migrations/config").getConfig; 9 | const serializeClaims = require("../test/helpers/identityClaims").serializeClaims; 10 | const Promise = require("bluebird"); 11 | // eslint-disable-next-line 12 | const Accounts = require("web3-eth-accounts"); 13 | const getDeployerAccount = require("../migrations/config").getDeployerAccount; 14 | 15 | const sendTransaction = Promise.promisify(web3.eth.sendTransaction); 16 | 17 | module.exports = async function investIntoETOPrepare() { 18 | const optionDefinitions = [ 19 | { name: "network", type: String }, 20 | { name: "universe", type: String }, 21 | { name: "pk", type: String }, 22 | { name: "amount", type: Number }, 23 | ]; 24 | 25 | const options = commandLineArgs(optionDefinitions, { partial: true }); 26 | const valid = options.network && options.universe && options.pk && options.amount; 27 | if (!valid) { 28 | throw new Error( 29 | "You didn't provide every one of required parameters: network, universe, pk, amount", 30 | ); 31 | } 32 | const DEPLOYER = getDeployerAccount(options.network, []); 33 | const address = Accounts.prototype.privateKeyToAccount(options.pk).address; 34 | console.log("Preparing system for testing investIntoETO script"); 35 | console.log(`Resolved PK to ${address}`); 36 | 37 | const CONFIG = getConfig(web3, options.network, []); 38 | const universe = await artifacts.require(CONFIG.artifacts.UNIVERSE).at(options.universe); 39 | const identityRegistry = await artifacts 40 | .require(CONFIG.artifacts.IDENTITY_REGISTRY) 41 | .at(await universe.identityRegistry()); 42 | await identityRegistry.setClaims( 43 | address, 44 | serializeClaims(false, false, false, false), 45 | serializeClaims(true, false, false, false), 46 | ); 47 | sendTransaction({ 48 | from: DEPLOYER, 49 | to: address, 50 | value: new web3.BigNumber(web3.toWei(options.amount, "ether")), 51 | }); 52 | }; 53 | -------------------------------------------------------------------------------- /scripts/solcs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | solc.4.24 -o ./build/ --overwrite --bin --allow-paths $(pwd)/contracts $@ 3 | -------------------------------------------------------------------------------- /scripts/solctruffle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | from="var result = solc.compileStandard(JSON.stringify(solcStandardInput));" 3 | to="var result = require('child_process').execSync('solc.4.26 --standard-json', {input: JSON.stringify(solcStandardInput)});" 4 | sed -i.bak "s/${from}/${to}/g" ./node_modules/truffle/build/cli.bundled.js 5 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # to be run via yarn test inprocess 3 | 4 | code=0 5 | for f in ./test/*.js 6 | do 7 | if [[ "$f" != *setup.js ]] 8 | then 9 | echo $f 10 | yarn truffle test $f ./test/setup.js --network $1 11 | code=$(($code + $?)) 12 | fi 13 | done 14 | exit $code 15 | -------------------------------------------------------------------------------- /test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-unused-expressions": ["off"] 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/ICBM/commitmentState.js: -------------------------------------------------------------------------------- 1 | // Needs to match contracts/ICBM/ICBMCommitment/ICBMStateMachine.sol:State 2 | export const CommitmentState = { 3 | Before: 0, 4 | Whitelist: 1, 5 | Public: 2, 6 | Finished: 3, 7 | }; 8 | -------------------------------------------------------------------------------- /test/ICBM/lockState.js: -------------------------------------------------------------------------------- 1 | export const LockState = { 2 | Uncontrolled: 0, 3 | AcceptingLocks: 1, 4 | AcceptingUnlocks: 2, 5 | ReleaseAll: 3, 6 | }; 7 | -------------------------------------------------------------------------------- /test/Mock.js: -------------------------------------------------------------------------------- 1 | import { deployTestReceiver } from "./helpers/tokenTestCases"; 2 | import { mockReceiverTests } from "./helpers/mockReceiverTestCases"; 3 | 4 | contract("Test Receiver", ([account1]) => { 5 | let receiver; 6 | const getReceiver = () => receiver; 7 | beforeEach(async () => { 8 | receiver = await deployTestReceiver(true); 9 | }); 10 | 11 | mockReceiverTests(getReceiver, account1); 12 | }); 13 | -------------------------------------------------------------------------------- /test/data/expectedCurveEuroAtIntegers.csv: -------------------------------------------------------------------------------- 1 | 0 2 | 1 3 | 2 4 | 3 5 | 4 6 | 5 7 | 6 8 | 7 9 | 8 10 | 9 11 | 10 12 | 20 13 | 30 14 | 40 15 | 50 16 | 60 17 | 70 18 | 80 19 | 90 20 | 100 21 | 200 22 | 300 23 | 400 24 | 500 25 | 600 26 | 700 27 | 800 28 | 900 29 | 1000 30 | 2000 31 | 3000 32 | 4000 33 | 5000 34 | 6000 35 | 7000 36 | 8000 37 | 9000 38 | 10000 39 | 20000 40 | 30000 41 | 40000 42 | 50000 43 | 60000 44 | 70000 45 | 80000 46 | 90000 47 | 100000 48 | 200000 49 | 300000 50 | 400000 51 | 500000 52 | 600000 53 | 700000 54 | 800000 55 | 900000 56 | 1000000 57 | 2000000 58 | 3000000 59 | 4000000 60 | 5000000 61 | 6000000 62 | 7000000 63 | 8000000 64 | 9000000 65 | 10000000 66 | 20000000 67 | 30000000 68 | 40000000 69 | 50000000 70 | 60000000 71 | 70000000 72 | 80000000 73 | 90000000 74 | 100000000 75 | 200000000 76 | 300000000 77 | 400000000 78 | 500000000 79 | 600000000 80 | 700000000 81 | 800000000 82 | 900000000 83 | 1000000000 84 | 1100000000 85 | 1200000000 86 | 1300000000 87 | 1400000000 88 | 1500000000 89 | 1600000000 90 | 1700000000 91 | 1800000000 92 | 1900000000 93 | 2000000000 94 | 2099999999.999999 95 | 2100000000 96 | 3000000000 97 | 4000000000 98 | 5000000000 99 | 6000000000 100 | 7000000000 101 | 8000000000 102 | 8299999999 103 | 8300000000 104 | 9000000000 105 | 10000000000 106 | 20000000000 107 | 30000000000 108 | 40000000000 109 | 50000000000 110 | 60000000000 111 | 70000000000 112 | 80000000000 113 | 90000000000 114 | -------------------------------------------------------------------------------- /test/helpers/EVMThrow.js: -------------------------------------------------------------------------------- 1 | export default "VM Exception"; 2 | -------------------------------------------------------------------------------- /test/helpers/artifacts.js: -------------------------------------------------------------------------------- 1 | // lists all artifacts that are deployed in migrations (without mocks which are configured in truffle.js) 2 | export const artifacts = { 3 | ROLE_BASED_ACCESS_POLICY: "RoleBasedAccessPolicy", 4 | ETHEREUM_FORK_ARBITER: "EthereumForkArbiter", 5 | NEUMARK: "Neumark", 6 | ICBM_LOCKED_ACCOUNT: "ICBMLockedAccount", 7 | ICBM_ETHER_TOKEN: "ICBMEtherToken", 8 | ICBM_EURO_TOKEN: "ICBMEuroToken", 9 | ICBM_COMMITMENT: "ICBMCommitment", 10 | UNIVERSE: "Universe", 11 | LOCKED_ACCOUNT: "LockedAccount", 12 | ETHER_TOKEN: "EtherToken", 13 | EURO_TOKEN: "EuroToken", 14 | EURO_TOKEN_CONTROLLER: "EuroTokenController", 15 | IDENTITY_REGISTRY: "IdentityRegistry", 16 | GAS_EXCHANGE: "SimpleExchange", 17 | PLATFORM_TERMS: "PlatformTerms", 18 | STANDARD_ETO_COMMITMENT: "ETOCommitment", 19 | STANDARD_EQUITY_TOKEN: "EquityToken", 20 | EQUITY_TOKEN_CONTROLLER: "SingleEquityTokenController", 21 | STANDARD_ETO_TERMS: "ETOTerms", 22 | STANDARD_TOKENHOLDER_RIGHTS: "EquityTokenholderRights", 23 | STANDARD_DURATION_TERMS: "ETODurationTerms", 24 | STANDARD_TOKEN_TERMS: "ETOTokenTerms", 25 | FEE_DISBURSAL: "FeeDisbursal", 26 | FEE_DISBURSAL_CONTROLLER: "FeeDisbursalController", 27 | // interfaces used in migrations 28 | TOKEN_EXCHANGE_RATE_ORACLE: "ITokenExchangeRateOracle", 29 | ETO_TERMS_CONSTRAINTS: "ETOTermsConstraints", 30 | VOTING_CENTER: "VotingCenter", 31 | VOTING_CENTER_CONTROLLER: "VotingController", 32 | EXIT_CONTROLLER: "ExitController", 33 | 34 | // not implemented 35 | // PLATFORM_PORTFOLIO: "IPlatformPortfolio" 36 | }; 37 | -------------------------------------------------------------------------------- /test/helpers/commitment.js: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { eventValue } from "./events"; 3 | 4 | export function expectLogFundsCommitted( 5 | tx, 6 | investor, 7 | wallet, 8 | paymentTokenAddress, 9 | amount, 10 | eurEquiv, 11 | expectedEquity, 12 | equityTokenAddress, 13 | expectedNeu, 14 | ) { 15 | const event = eventValue(tx, "LogFundsCommitted"); 16 | expect(event).to.exist; 17 | expect(event.args.investor).to.eq(investor); 18 | expect(event.args.wallet).to.eq(wallet); 19 | expect(event.args.paymentToken).to.eq(paymentTokenAddress); 20 | expect(event.args.amount).to.be.bignumber.eq(amount); 21 | expect(event.args.baseCurrencyEquivalent).to.be.bignumber.eq(eurEquiv); 22 | expect(event.args.grantedAmount).to.be.bignumber.eq(expectedEquity); 23 | expect(event.args.assetToken).to.eq(equityTokenAddress); 24 | expect(event.args.neuReward).to.be.bignumber.eq(expectedNeu); 25 | } 26 | -------------------------------------------------------------------------------- /test/helpers/commitmentState.js: -------------------------------------------------------------------------------- 1 | // Needs to match contracts/ETO/IETOCommitmentStates:State 2 | export const CommitmentState = { 3 | Setup: 0, 4 | Whitelist: 1, 5 | Public: 2, 6 | Signing: 3, 7 | Claim: 4, 8 | Payout: 5, 9 | Refund: 6, 10 | }; 11 | 12 | export const CommitmentStateRev = Object.keys(CommitmentState).reduce( 13 | (obj, x) => Object.assign(obj, { [CommitmentState[x]]: x }), 14 | {}, 15 | ); 16 | -------------------------------------------------------------------------------- /test/helpers/constants.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | 3 | export const web3 = new Web3(); 4 | export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 5 | export const ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000"; 6 | export const decimalBase = new web3.BigNumber("10"); 7 | export const ZERO_BN = new web3.BigNumber("0"); 8 | export const Q18 = decimalBase.pow("18"); 9 | export const Q16 = decimalBase.pow("16"); 10 | export const DAY_SNAPSHOT = new web3.BigNumber(2).pow(128); 11 | export const hourInSeconds = 60 * 60; 12 | export const dayInSeconds = 24 * hourInSeconds; 13 | export const monthInSeconds = 30 * dayInSeconds; 14 | export const daysToSeconds = sec => sec * dayInSeconds; 15 | export const hoursToSeconds = sec => sec * hourInSeconds; 16 | // default scale and power of equity token as used by fixtures and default test terms 17 | // allow to override from env variable to run ETO tests several scales 18 | export const defEquityTokenDecimals = new web3.BigNumber(process.env.EQUITY_TOKEN_DECIMALS || "18"); 19 | export const defEquityTokenPower = decimalBase.pow(defEquityTokenDecimals); 20 | // default tokens per share used as above 21 | export const defaultTokensPerShare = defEquityTokenPower.mul(new web3.BigNumber("1000000")); 22 | -------------------------------------------------------------------------------- /test/helpers/createAccessPolicy.js: -------------------------------------------------------------------------------- 1 | const { TriState, EVERYONE, GLOBAL } = require("./triState"); 2 | 3 | export default async (rbap, rules) => { 4 | if (!rules || rules.length === 0) { 5 | return; 6 | } 7 | const completedRules = rules.map(rule => 8 | Object.assign({ subject: EVERYONE, object: GLOBAL, state: TriState.Allow }, rule), 9 | ); 10 | await rbap.setUserRoles( 11 | completedRules.map(({ subject }) => subject), 12 | completedRules.map(({ role }) => role), 13 | completedRules.map(({ object }) => object), 14 | completedRules.map(({ state }) => state), 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /test/helpers/dataset.js: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | 3 | export function parseNmkDataset(fileName) { 4 | // parses CSV file generated from Mathematica. All numbers have 36 digits precision to approximate 18 decimals scale of Neumark token 5 | const lines = fs 6 | .readFileSync(fileName) 7 | .toString() 8 | .split("\n") 9 | .filter(line => line.length > 0); 10 | 11 | return lines.map(line => { 12 | const eurNmk = line.split(","); 13 | return [new web3.BigNumber(eurNmk[0]).round(18, 4), new web3.BigNumber(eurNmk[1]).round(18, 4)]; 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /test/helpers/disbursal.js: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { eventValue } from "./events"; 3 | 4 | export function expectLogDisbursalCreated( 5 | tx, 6 | proRataToken, 7 | token, 8 | amount, 9 | disburserAddr, 10 | recycleDur, 11 | index, 12 | ) { 13 | const event = eventValue(tx, "LogDisbursalCreated"); 14 | expect(event).to.exist; 15 | expect(event.args.proRataToken).to.eq(proRataToken); 16 | expect(event.args.token).to.eq(token); 17 | expect(event.args.amount).to.be.bignumber.eq(amount); 18 | expect(event.args.recycleAfterDuration).to.be.bignumber.eq(recycleDur); 19 | expect(event.args.disburser).to.eq(disburserAddr); 20 | if (index) { 21 | expect(event.args.index).to.be.bignumber.eq(index); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/helpers/evmCommands.js: -------------------------------------------------------------------------------- 1 | import { promisify } from "./utils"; 2 | 3 | export const rpcCommand = method => async (...params) => 4 | ( 5 | await promisify(web3.currentProvider.sendAsync)({ 6 | jsonrpc: "2.0", 7 | method, 8 | params, 9 | id: Date.now(), 10 | }) 11 | ).result; 12 | 13 | export const mineBlock = rpcCommand("evm_mine"); 14 | export const increaseTime = rpcCommand("evm_increaseTime"); 15 | export const saveBlockchain = rpcCommand("evm_snapshot"); 16 | export const restoreBlockchain = rpcCommand("evm_revert"); 17 | -------------------------------------------------------------------------------- /test/helpers/forceEther.js: -------------------------------------------------------------------------------- 1 | const ForceEther = artifacts.require("ForceEther"); 2 | 3 | export default async (address, amountWei, fromAddress) => { 4 | const forceEther = await ForceEther.new({ 5 | value: amountWei, 6 | from: fromAddress, 7 | }); 8 | await forceEther.pay(address); 9 | }; 10 | -------------------------------------------------------------------------------- /test/helpers/gasUtils.js: -------------------------------------------------------------------------------- 1 | import { promisify } from "./utils"; 2 | 3 | export const weiPrice = 300e-18; // http://coincap.io/ 4 | export const gasPrice = 21e9 * weiPrice; // https://ethstats.net 5 | export const gasLimit = 6712392; // https://ethstats.net 6 | 7 | const gasCostString = gas => 8 | `${gas} gas (€${Math.round(100 * gas * gasPrice) / 100}, ${Math.round((1000 * gas) / gasLimit) / 9 | 10}% of limit)`; 10 | 11 | export const txGasCost = tx => tx.receipt.gasUsed; 12 | 13 | export const gasCost = async obj => { 14 | if (Number.isInteger(obj)) { 15 | return obj; 16 | } 17 | if (obj.receipt) { 18 | return obj.receipt.gasUsed; 19 | } 20 | 21 | const receipt = await promisify(web3.eth.getTransactionReceipt)(obj.transactionHash); 22 | return receipt.gasUsed; 23 | }; 24 | 25 | export const prettyPrintGasCost = async (what, obj) => { 26 | const gas = await gasCost(obj); 27 | 28 | // eslint-disable-next-line no-console 29 | console.log(`\t${what} took ${gasCostString(gas)}`); 30 | }; 31 | 32 | export const printCodeSize = async (what, obj) => { 33 | let addr; 34 | if (typeof obj === "string") { 35 | addr = obj; 36 | } else if (obj.address) { 37 | addr = obj.address; 38 | } 39 | const code = await promisify(web3.eth.getCode)(addr); 40 | // eslint-disable-next-line no-console 41 | console.log(`\t${what} code size is ${code.length / 2 - 1}`); 42 | }; 43 | -------------------------------------------------------------------------------- /test/helpers/identityClaims.js: -------------------------------------------------------------------------------- 1 | const Web3 = require("web3"); 2 | const toBytes32 = require("./utils").toBytes32; 3 | 4 | const web3 = new Web3(); 5 | 6 | export const identityClaims = { 7 | isNone: 0, 8 | isVerified: 1, 9 | isSophisticatedInvestor: 2, 10 | hasBankAccount: 4, 11 | isAccountFrozen: 8, 12 | requiresRegDAccreditation: 16, 13 | hasValidRegDAccreditation: 32, 14 | }; 15 | 16 | export function serializeClaims( 17 | isVerified, 18 | isSophisticatedInvestor, 19 | hasBankAccount, 20 | isAccountFrozen, 21 | requiresRegDAccreditation = false, 22 | hasValidRegDAccreditation = false, 23 | ) { 24 | const claims = 25 | (isVerified ? identityClaims.isVerified : 0) + 26 | (isSophisticatedInvestor ? identityClaims.isSophisticatedInvestor : 0) + 27 | (hasBankAccount ? identityClaims.hasBankAccount : 0) + 28 | (isAccountFrozen ? identityClaims.isAccountFrozen : 0) + 29 | (requiresRegDAccreditation ? identityClaims.requiresRegDAccreditation : 0) + 30 | (hasValidRegDAccreditation ? identityClaims.hasValidRegDAccreditation : 0); 31 | 32 | return toBytes32(claims); 33 | } 34 | 35 | export function deserializeClaims(claims) { 36 | const claimsN = new web3.BigNumber(claims, 16); 37 | return referenceClaims( 38 | claimsN.mod(2).eq(1), 39 | claimsN 40 | .dividedToIntegerBy(2) 41 | .mod(2) 42 | .eq(1), 43 | claimsN 44 | .dividedToIntegerBy(4) 45 | .mod(2) 46 | .eq(1), 47 | claimsN 48 | .dividedToIntegerBy(8) 49 | .mod(2) 50 | .eq(1), 51 | claimsN 52 | .dividedToIntegerBy(16) 53 | .mod(2) 54 | .eq(1), 55 | claimsN 56 | .dividedToIntegerBy(32) 57 | .mod(2) 58 | .eq(1), 59 | ); 60 | } 61 | 62 | export function referenceClaims( 63 | isVerified, 64 | isSophisticatedInvestor, 65 | hasBankAccount, 66 | accountFrozen, 67 | requiresRegDAccreditation = false, 68 | hasValidRegDAccreditation = false, 69 | ) { 70 | return [ 71 | { isVerified }, 72 | { isSophisticatedInvestor }, 73 | { hasBankAccount }, 74 | { accountFrozen }, 75 | { requiresRegDAccreditation }, 76 | { hasValidRegDAccreditation }, 77 | ]; 78 | } 79 | -------------------------------------------------------------------------------- /test/helpers/increaseTime.js: -------------------------------------------------------------------------------- 1 | import moment from "moment"; 2 | import { latestTimestamp } from "./latestTime"; 3 | // Increases testrpc time by the passed duration (a moment.js instance) 4 | async function increaseTime(duration) { 5 | const id = Date.now(); 6 | 7 | return new Promise((resolve, reject) => { 8 | web3.currentProvider.sendAsync( 9 | { 10 | jsonrpc: "2.0", 11 | method: "evm_increaseTime", 12 | params: [typeof duration === "object" ? duration.asSeconds() : duration], 13 | id, 14 | }, 15 | (err1, result) => { 16 | if (err1) { 17 | reject(err1); 18 | return; 19 | } 20 | if (result.error) { 21 | reject(`increaseTime not supported, test will fail ${result.error}`); 22 | } 23 | web3.currentProvider.sendAsync( 24 | { 25 | jsonrpc: "2.0", 26 | method: "evm_mine", 27 | id: id + 1, 28 | }, 29 | (err2, res) => (err2 ? reject(err2) : resolve(res)), 30 | ); 31 | }, 32 | ); 33 | }); 34 | } 35 | // need to be split into separate statements https://github.com/babel/babel/issues/3786 36 | export default increaseTime; 37 | 38 | // sets time to given timestamp based on current block time 39 | export async function setTimeTo(timestamp) { 40 | const ct = await latestTimestamp(); 41 | if (ct > timestamp) { 42 | throw new Error(`cannot decrease time to ${timestamp} from ${ct}`); 43 | } 44 | return increaseTime(moment.duration(timestamp - ct, "s")); 45 | } 46 | -------------------------------------------------------------------------------- /test/helpers/knownInterfaces.js: -------------------------------------------------------------------------------- 1 | const sha3Web3 = require("web3/lib/utils/sha3"); 2 | 3 | function sha3(s) { 4 | return `0x${sha3Web3(s)}`; 5 | } 6 | 7 | // lists all known interfaces which provide same services with different concrete implementations (abis) 8 | export const knownInterfaces = { 9 | accessPolicy: sha3("IAccessPolicy").slice(0, 10), 10 | forkArbiter: sha3("IEthereumForkArbiter").slice(0, 10), 11 | neumark: sha3("Neumark").slice(0, 10), 12 | etherToken: sha3("EtherToken").slice(0, 10), 13 | euroToken: sha3("EuroToken").slice(0, 10), 14 | euroTokenController: sha3("EuroTokenController").slice(0, 10), 15 | identityRegistry: sha3("IIdentityRegistry").slice(0, 10), 16 | tokenExchangeRateOracle: sha3("ITokenExchangeRateOracle").slice(0, 10), 17 | feeDisbursal: sha3("IFeeDisbursal").slice(0, 10), 18 | platformPortfolio: sha3("IPlatformPortfolio").slice(0, 10), 19 | tokenExchange: sha3("ITokenExchange").slice(0, 10), 20 | gasExchange: sha3("IGasTokenExchange").slice(0, 10), 21 | euroLock: sha3("LockedAccount:Euro").slice(0, 10), 22 | etherLock: sha3("LockedAccount:Ether").slice(0, 10), 23 | icbmEuroLock: sha3("ICBMLockedAccount:Euro").slice(0, 10), 24 | icbmEtherLock: sha3("ICBMLockedAccount:Ether").slice(0, 10), 25 | icbmEtherToken: sha3("ICBMEtherToken").slice(0, 10), 26 | icbmEuroToken: sha3("ICBMEuroToken").slice(0, 10), 27 | icbmCommitment: sha3("ICBMCommitment").slice(0, 10), 28 | platformTerms: sha3("PlatformTerms").slice(0, 10), 29 | universe: sha3("Universe").slice(0, 10), 30 | commitmentInterface: sha3("ICommitment").slice(0, 10), 31 | equityTokenInterface: sha3("IEquityToken").slice(0, 10), 32 | equityTokenControllerInterface: sha3("IEquityTokenController").slice(0, 10), 33 | termsInterface: sha3("IOfferingTerms").slice(0, 10), 34 | paymentTokenInterface: sha3("PaymentToken").slice(0, 10), 35 | etoTermsConstraints: sha3("ETOTermsConstraints").slice(0, 10), 36 | votingCenter: sha3("IVotingCenter").slice(0, 10), 37 | exitController: sha3("ExitController").slice(0, 10), 38 | }; 39 | -------------------------------------------------------------------------------- /test/helpers/latestTime.js: -------------------------------------------------------------------------------- 1 | import { mineBlock } from "./evmCommands"; 2 | import { promisify } from "./utils"; 3 | 4 | let firstTimeRequestedTime = true; 5 | 6 | export async function latestTimestamp() { 7 | // this is done as a workaround for a bug when first requested block get return wrong timestamp 8 | if (firstTimeRequestedTime) { 9 | await mineBlock(); 10 | firstTimeRequestedTime = false; 11 | } 12 | 13 | return (await promisify(web3.eth.getBlock)("latest")).timestamp; 14 | } 15 | 16 | export async function txTimestamp(tx) { 17 | return (await promisify(web3.eth.getBlock)(tx.receipt.blockNumber)).timestamp; 18 | } 19 | -------------------------------------------------------------------------------- /test/helpers/promiseUtils.js: -------------------------------------------------------------------------------- 1 | export async function sequence(array, promiseGenerator) { 2 | const results = []; 3 | for (const item of array) { 4 | results.push(await promiseGenerator(item)); 5 | } 6 | 7 | return results; 8 | } 9 | -------------------------------------------------------------------------------- /test/helpers/registerSingletons.js: -------------------------------------------------------------------------------- 1 | export default async (universe, owner, interfaces) => { 2 | if (!interfaces || interfaces.length === 0) { 3 | return; 4 | } 5 | /* eslint-disable consistent-return */ 6 | return universe.setManySingletons( 7 | interfaces.map(({ ki }) => ki), 8 | interfaces.map(({ addr }) => addr), 9 | { from: owner }, 10 | ); 11 | }; 12 | -------------------------------------------------------------------------------- /test/helpers/relayedVoteSigning.js: -------------------------------------------------------------------------------- 1 | const web3Utils = require("web3-utils"); 2 | 3 | // NOTE web3.personal.sign & web3.eth.sign were both erroring, so I built this workaround 4 | const evmSign = function(address, message) { 5 | const id = Date.now(); 6 | return new Promise((resolve, reject) => { 7 | web3.currentProvider.sendAsync( 8 | { 9 | jsonrpc: "2.0", 10 | method: "eth_sign", 11 | params: [address, message], 12 | id, 13 | }, 14 | (err, res) => (err ? reject(err) : resolve(res.result)), 15 | ); 16 | }); 17 | }; 18 | 19 | // Create a signed message that @param voter wants to vote @param inFavor of the proposal with 20 | // @param proposalIndex at the votingContract at address @param votingContract 21 | export async function createSignedVote(proposalId, inFavor, voter, votingContract) { 22 | // using EIP 191 signature scheme version 0 (intended validator) 23 | const msg = web3Utils.soliditySha3( 24 | { type: "bytes1", value: "0x0" }, 25 | { type: "address", value: votingContract }, 26 | { type: "bytes32", value: proposalId }, 27 | { type: "bool", value: inFavor }, 28 | ); 29 | const sig = await evmSign(voter, msg); 30 | return [ 31 | sig.substr(0, 66), 32 | "0x".concat(sig.substr(66, 64)), 33 | parseInt(sig.substr(130, 2), 16) + 27, 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /test/helpers/roles.js: -------------------------------------------------------------------------------- 1 | const sha3Web3 = require("web3/lib/utils/sha3"); 2 | 3 | function sha3(s) { 4 | return `0x${sha3Web3(s)}`; 5 | } 6 | 7 | export default { 8 | accessController: sha3("AccessController"), 9 | example: sha3("Example"), 10 | platformOperatorRepresentative: sha3("PlatformOperatorRepresentative"), 11 | lockedAccountAdmin: sha3("LockedAccountAdmin"), 12 | neumarkBurner: sha3("NeumarkBurner"), 13 | neumarkIssuer: sha3("NeumarkIssuer"), 14 | reclaimer: sha3("Reclaimer"), 15 | snapshotCreator: sha3("SnapshotCreator"), 16 | transferAdmin: sha3("TransferAdmin"), 17 | whitelistAdmin: sha3("WhitelistAdmin"), 18 | eurtDepositManager: sha3("EurtDepositManager"), 19 | universeManager: sha3("UniverseManager"), 20 | identityManager: sha3("IdentityManager"), 21 | eurtLegalManager: sha3("EurtLegalManager"), 22 | gasExchange: sha3("GasExchange"), 23 | tokenRateOracle: sha3("TokenRateOracle"), 24 | disburser: sha3("Disburser"), 25 | disbursalManager: sha3("DisbursalManager"), 26 | companyUpgradeAdmin: sha3("CompanyUpgradeAdmin"), 27 | votingCenterManager: sha3("VotingCenterManager"), 28 | votingInitiator: sha3("VotingInitator"), 29 | }; 30 | -------------------------------------------------------------------------------- /test/helpers/termsConstants.js: -------------------------------------------------------------------------------- 1 | // Needs to match ETOTermsConstraints contract types 2 | 3 | export const OfferingDocumentType = { 4 | Memorandum: 0, 5 | Prospectus: 1, 6 | }; 7 | 8 | export const OfferingDocumentSubType = { 9 | Regular: 0, 10 | Lean: 1, 11 | }; 12 | 13 | export const AssetType = { 14 | Security: 0, 15 | VMA: 1, 16 | }; 17 | -------------------------------------------------------------------------------- /test/helpers/triState.js: -------------------------------------------------------------------------------- 1 | // Needs to match contracts/AccessControl/RoleBasedAccessPolicy.sol:TriState 2 | export const TriState = { Unset: 0, Allow: 1, Deny: 2 }; 3 | export const EVERYONE = "0x0000000000000000000000000000000000000000"; 4 | export const GLOBAL = "0x0000000000000000000000000000000000000000"; 5 | -------------------------------------------------------------------------------- /test/helpers/unitConverter.js: -------------------------------------------------------------------------------- 1 | const BigNumber = web3.BigNumber; 2 | 3 | export function etherToWei(number) { 4 | return new BigNumber(web3.toWei(number, "ether")); 5 | } 6 | 7 | export function shanToWei(number) { 8 | return new BigNumber(web3.toWei(number, "shannon")); 9 | } 10 | 11 | export const divRound = (v, d) => 12 | d 13 | .divToInt(2) 14 | .plus(v) 15 | .divToInt(d); 16 | -------------------------------------------------------------------------------- /test/helpers/voting.js: -------------------------------------------------------------------------------- 1 | export const ProposalState = { Campaigning: 0, Public: 1, Reveal: 2, Tally: 3, Final: 4 }; 2 | export const VotingTriState = { Abstain: 0, InFavor: 1, Against: 2 }; 3 | -------------------------------------------------------------------------------- /test/lockState.js: -------------------------------------------------------------------------------- 1 | export const LockState = { 2 | AcceptingUnlocks: 0, 3 | ReleaseAll: 1, 4 | }; 5 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | // THIS FILE IS JUST A WORKAROUND FOR PROBLEMS WITH WORKING WITH MOCHA+TRUFFLE 2 | // normaly you would just use --require option in mocha and setup tests there 3 | require("../mocha"); 4 | --------------------------------------------------------------------------------