Neufund / platform-contracts

Smart contract for Neufund platform
MIT License
36 stars 32 forks source link

CLI for shifting time of mock ETOs #312

Closed rudolfix closed 4 years ago

rudolfix commented 5 years ago

Why we do it We have several under-tested ETO state transition cases that were already an visible on production and are quite hard to add as an permanent fixtures. In essence we want to e2e and manually test following cases

What need to be implemented Implement a CLI in platform contracts repo, similar to deployETO.js or inspectETO.js that when run via truffle will mock internal state of ETO to simulate state transitions.

Technical Details

On dev networks we deploy MockETOCommitment contract instead ETOCommitment Mock contract, among other things, allows to mock internal timestamps of ETO state machine (See _mockShiftBackTime). Look for method usage in existing code. For reference please read https://github.com/Neufund/platform-backend/wiki/5.06.-Use-Case-Investment - ETO State machine reference https://github.com/Neufund/platform-contracts/wiki/Smart-Contracts-Catalogue#platformterms-etoterms-durationterms-and-shareholderrights - a kind of primer on ETO Contracts

Acceptance Criteria

Testing Manual testing would be enough, you can also unit test shiftting function if it's not yet...

Deployment

djudjuu commented 5 years ago

UPDATE:

in conversation with FE and backend, we figured the most appropriate solution will be to offer this as a service over an api-endpoint. this will enable e2e tests for the frontend.

Also, we could just write the shift into a soldity function, that way it will be easier tested by the backend-unit tests (i do not understand why yet)

see this PR in backed-repo too: https://github.com/Neufund/platform-backend/pull/2275

djudjuu commented 4 years ago

here are my notes on solving this task:

===========

Table of Contents

  1. TASK1: CLI for ETO Tests
    1. read issue descriptions
    2. what states does an ETO go through? -> 7, see IETOCommitmentStates.sol
    3. how to know when next state transition will happen?
    4. where to compute by how much to shift? Solidity > JS
    5. put it on its own branch
    6. which repo to work in ??
      1. work in backend repo
    7. in contract repo
      1. understand how to query state
      2. write basic truffle test
      3. write js-script to be invoked by cmdLine
      4. example says signing to refund… how to manipulate the contract so that it goes that way?
      5. BUG:SOLVED shifting to state after public with _mockPastTime causes errors
      6. implement function in commandline-tool
    8. backend repo:
      1. adjust the script to work via an exposed api
      2. test pipeline
      3. learn python blockchain :
    9. run script via an API endpoint
      1. define api-endpoint in backend/
    10. wrap api in a service
    11. define error-classes
    12. Write helper to fetch address from fixture name STALLED
    13. write tests for service -> does not need to be done,
    14. NOT DONE readup on git submodules > some other time
    15. add test for eto not in universe
      1. helper notes
    16. implement helper function on contract directly
      1. STOPPED move contract implementation to backend-repo so that I can deploy the new MockEto contract -> increase GAS LIMIT on parity node
      2. increase gasLimit of parity-node
      3. what are all the networks in truffle.js
    17. create gaslimit raising prs
    18. move script implementation to backend-repo -> STOPPED
    19. DO a JS implementation to be used by frontend-devs STUCK
    20. test it by looking at deployed frontend (build frontend notes)
    21. change endpoint to use the newly created helper on contract
      1. use updated contracts in backend-repo:
    22. test pipeline
    23. WHERE AM I NOW?
    24. show merged PR to Moe, learn together with Nicole how to use it
      1. test whether invalid args return helpful messages
    25. PRS to be merged:

DONE TASK1: CLI for ETO Tests

TODO read issue descriptions

DONE what states does an ETO go through? -> 7, see IETOCommitmentStates.sol

ETOState. Setup Whitelist Public Signing Refund Payout

DONE how to know when next state transition will happen?

DONE where to compute by how much to shift? Solidity > JS

=> for now, implemented in solidity, using startOfInternal js would use startOfStates

trouble as ETOCOmmitment is pretty big…

DONE put it on its own branch

DONE which repo to work in ??

work in backend repo

in contract repo

DONE understand how to query state

some tests use CommitmentState.js, whcih abstracts to 4 states vs the 7 defined in ETOStat whcih f to use to understand ETO state? there are various CommitmentState-enums defined, I need to use the one in ``helpers/CommitmentState.js`` -> expectLogStateTransition

DONE write basic truffle test

yarn build
then run individual test

yarn truffle test –network inprocesstest test/ETO/ETOCommitment.js test/setup.js

does not compile, run solc on it first

  1. extra test here:

    it("should move time to right before state transition", async () => {

    await deployETO({ ovrArtifact: MockETOCommitment }); const timestamp = await latestTimestamp(); durTable = defaultDurationTable(); startDate = new web3.BigNumber(timestamp + 2 * dayInSeconds); const whitelistD = durTable[CommitmentState.Whitelist].add(1); // set start data to 2 days from now via mocker const startTx = await etoCommitment.mockStartDate( etoTerms.address, equityToken.address, startDate, startDate.add(whitelistD), { from: company }, ); expectLogETOStartDateSet(startTx, company, 0, startDate.add(whitelistD));

    // move to right before startDate via helper and wait await etoCommitment.shiftToBeforeNextState(10); await increaseTime(15); const tx = await etoCommitment.handleStateTransitions(); expectLogStateTransition(tx, CommitmentState.Setup, CommitmentState.Whitelist, "ignore");

    // do so again for whitelist->public transition await etoCommitment.shiftToBeforeNextState(10); await increaseTime(15); const tx2 = await etoCommitment.handleStateTransitions(); expectLogStateTransition(tx2, CommitmentState.Whitelist, CommitmentState.Public, "ignore" ); });

DONE write js-script to be invoked by cmdLine

TODO example says signing to refund… how to manipulate the contract so that it goes that way?

DONE BUG:SOLVED shifting to state after public with _mockPastTime causes errors

-> shift all states so that one can not cause illogical states where a previous state ends before the next one

DONE implement function in commandline-tool

backend repo:

adjust the script to work via an exposed api

always use make down before doing things

test pipeline

make update-service service=devexternalservicesmockapi

use docker ps to get id docker kill id

navigate to /devexternalmockapi and start manually python runapi.py

"type": "platformcontracts.exceptions.PlatformContractsContractNotDeployed"

TODO learn python blockchain :

check py3 docs full instance 4 transactions vs instance (call only) method().transact() method().call()

DONE run script via an API endpoint

define api-endpoint in backend/

yaml and in e2etests.py

DONE wrap api in a service

DONE define error-classes

Write helper to fetch address from fixture name STALLED

DONE write tests for service -> does not need to be done,

for this specific endpoint, we need no tests as it will be tested by the frontend implicitly

in general: make test im richtigen verzeichnis make test in root => all

NOT DONE readup on git submodules > some other time

DONE add test for eto not in universe

where to get interface from? Tomek send me a bunch of useful links to helper on slack:

helper notes

or maybe like this function getetofixtureaddress from platformtesting/platformcontracts.py in platform common (edited)  70m3k 1:25 PM def obtainetotermscontract(etoid: str) -> ConciseContract: connector = NeufundContractsConnector(ethereumserviceconfiguration) neufundcontracts = connector.getneufundcontracts() commitmentartifact = neufundcontracts.resolveartifactfrominterface("commitmentInterface", etoid) etocontract = neufundcontracts.getinstance(commitmentartifact, etoid) etotermsaddress = etocontract.etoTerms() termsartifact = neufundcontracts.resolveartifactfrominterface("termsInterface", etotermsaddress) return neufundcontracts.getinstance(termsartifact, etotermsaddress) new messages 1:27 PM again from pyplatformcommon now file platformtesting/utils/ethereumhelpers.py there is getetocontract function with etoaddress as parameter (edited) 1:28 PM and snippet I've sent you earlier could rewritten using getetocontract function 

DONE implement helper function on contract directly

STOPPED move contract implementation to backend-repo so that I can deploy the new MockEto contract -> increase GAS LIMIT on parity node

?? how to increase gas-limit used in migrations? why does it work in the truffle test, but not in the backend-fixture deployment?

DONE increase gasLimit of parity-node

  1. DONE gas limit check

    parity node vs latest raise

    https://ethgasstation.info/blog/ethereum-block-size/

DONE what are all the networks in truffle.js

LEARNED:

live mirrors mainnet

everything with test can use DEV things

DONE create gaslimit raising prs

on both contracts and parity s see task "implement helper function on contract directly"

DONE move script implementation to backend-repo -> STOPPED

BLOCKED backend repo can not run truffle properly

DONE DO a JS implementation to be used by frontend-devs STUCK

?? why is BigNumber always used via web3? ?? How to get the current time in script? Blocktime does not work out of the box, maybe just use unix timestamp -> ask Moe

->

DONE test it by looking at deployed frontend (build frontend notes)

-> deploy frontend!

DONE change endpoint to use the newly created helper on contract

use updated contracts in backend-repo:

make update-submodules

make down & make test unit … got an error:
*root*.node-gyp/8.16.2/include/node/v8.h:3370:19: warning: inline function 'void\* v8::Object::GetAlignedPointerFromInternalField(int)' used but never defined

V8INLINE void* GetAlignedPointerFromInternalField(int index); ^~~~~~~~~~ make: * [scrypt.target.mk:121: Release/obj.target/scrypt/src/node-boilerplate/scryptcommon.o] Error 1 gyp ERR! build error gyp ERR! stack Error: `make` failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/nodemodules/npm/nodemodules/node-gyp/lib/build.js:262:23) gyp ERR! stack at emitTwo (events.js:126:13) gyp ERR! stack at ChildProcess.emit (events.js:214:7) gyp ERR! stack at Process.ChildProcess.handle.onexit (internal/childprocess.js:198:12) gyp ERR! System Linux 5.0.0-32-generic gyp ERR! command \"/usr/local/bin/node\" \"/usr/local/lib/nodemodules/npm/nodemodules/node-gyp/bin/node-gyp.js\" \"rebuild\" gyp ERR! cwd /usr/src/platform-contracts/nodemodules/scrypt gypmake: Leaving directory '/usr/src/platform-contracts/nodemodules/scrypt/build' ERR! node -v v8.16.2 gyp ERR! node-gyp -v v3.8.0 gyp ERR! not ok"

test pipeline

go to backend node at http://localhost:1337/ui/#!/e2e-tests/api_e2etests_eto_time_travel

get deployed contract address from fixture log make run fixtures

DONE WHERE AM I NOW?

DONE show merged PR to Moe, learn together with Nicole how to use it

TODO test whether invalid args return helpful messages

nicola uses it via postman

PRS to be merged: