Giter Club home page Giter Club logo

reach-sh / reach-lang Goto Github PK

View Code? Open in Web Editor NEW
587.0 17.0 169.0 204.41 MB

Reach: The Safest and Smartest DApp Programming Language

Home Page: https://www.reach.sh

License: Apache License 2.0

Makefile 0.79% Haskell 47.34% Shell 1.64% SMT 0.12% JavaScript 13.74% Dockerfile 0.30% Racket 0.05% Python 1.00% HTML 0.34% TypeScript 33.65% Solidity 0.25% Go 0.16% C# 0.20% CSS 0.09% MDX 0.33%
blockchain dapps-development dsl algorand conflux ethereum nfts

reach-lang's Introduction

Have a question?

Let's talk. Start a GitHub Discussion

Reach

CircleCI Build Status GitHub License Docs Discord Twitter Follow Subreddit subscribers

We are building the next generation blockchain development platform that will completely transform the paradigm of decentralized application (DApp) development. DApps have enormous potential, but are impractical today because of barriers that have kept blockchain development risky and limited to specialists, like cryptographers. The Reach platform is a comprehensive environment that enables junior developers to build useful and safe DApps without years of experience and easily deploy them on a variety of different blockchain networks.

This repository is for the Reach language, the domain-specific language for trustworthy DApps used by the Reach platform.

Read the documentation.

Development

If you want to work on the Reach compiler, you'll need:

The versions of our dependencies are specified in DEPS.

Installation on macOS:

$ brew tap ethereum/ethereum
$ brew install haskell-stack z3 solidity
$ curl -sSL https://git.io/get-mo -o mo && chmod +x mo && sudo mv mo /usr/local/bin/

Installation on Ubuntu:

$ sudo apt update
$ sudo apt install z3
$ sudo snap install solc
$ curl -sSL https://get.haskellstack.org/ | sh
$ curl -sSL https://git.io/get-mo -o mo && chmod +x mo && sudo mv mo /usr/local/bin/

These instructions may not install the exactly correct versions, and that may matter. If it does, consult hs/Dockerfile.reachc to learn how to get specific versions.

The source code is in the hs directory.

reach-lang's People

Contributors

awoldes avatar brohamgoham avatar cbaunach avatar chikeabuah avatar chrisnevers avatar craig-elre avatar danburton avatar dependabot[bot] avatar eberegit avatar erer1243 avatar ericglau avatar hagenhaus avatar hamirmahal avatar jeapostrophe avatar kbryan avatar keeganthomp avatar kimmyg avatar mattaudesse avatar nstanford5 avatar omahs avatar phoniks avatar pirovanomg avatar reekamaharaj avatar temptemp3 avatar thechronicmonster avatar thegaram avatar tippenein avatar vinmazzi avatar willghatch avatar xarmian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reach-lang's Issues

Error while parsing $ - expected Object, but encountered Null

Here is a dump from the error.
make build
docker build --build-arg REACHC_HASH="$(../scripts/git-hash.sh)" --tag="reachsh/reach":latest .
Sending build context to Docker daemon 1.041MB
Step 1/28 : FROM reachsh/haskell-builder:lts-16.12 as build
lts-16.12: Pulling from reachsh/haskell-builder
5d9821c94847: Already exists
a610eae58dfc: Already exists
a40e0eb9f140: Already exists
f5a1b3beb4d5: Pulling fs layer
00f60e56d58b: Pulling fs layer
7da1d9ee2c39: Pulling fs layer
bdcf8775a817: Pulling fs layer
02841cf00f57: Pulling fs layer
6d7b2c61f61a: Pull complete
76f8f84115ee: Pull complete
90a2e469cc7e: Pull complete
0531acd88941: Pull complete
4fd332f6d9c4: Pull complete
d515aee5fda5: Pull complete
Digest: sha256:8de67a4cd2f820b97cfa0b6b7bd18c11a694aaaeab49206387965351dfb57eb1
Status: Downloaded newer image for reachsh/haskell-builder:lts-16.12
---> 692b7e335c77
Step 2/28 : WORKDIR /build
---> Running in 01b510fb14e1
Removing intermediate container 01b510fb14e1
---> f460fba3481e
Step 3/28 : COPY stack.yaml package.yaml stack.yaml.lock ./
---> 4757f74e10af
Step 4/28 : RUN stack build --dependencies-only
---> Running in bdb9a29d3b80
/build/package.yaml: Error while parsing $ - expected Object, but encountered Null
The command '/bin/bash -o pipefail -c stack build --dependencies-only' returned a non-zero code: 1
make: *** [build] Error 1

Unhandled Rejection (Error) ETH : Ad51,Ad51,send,m8,false,SEND REPEAT @ 9725293 x 33

While assisting a community member. We witnessed this error.

312 | const txn5 = await (ctc.sendrecv(8, 1, stdlib.checkedBigNumberify('./index.rsh:394:15:dot', stdlib.UInt_max, 9), [ctc6, ctc0, ctc6, ctc6, ctc0, ctc0, ctc0, ctc8, ctc10, ctc0, ctc3], [v24, v25, v32, v39, v173, v175, v177, v178, v197, v322, v221], [stdlib.checkedBigNumberify('./index.rsh:decimal', stdlib.UInt_max, 0), []], [ctc3], true, true, false, (async (txn5) => {
| ^ 313 | const sim_r = { txns: [], mapRefs: [], mapsPrev: [], mapsNext: [] };
314 |
315 | sim_r.prevSt = stdlib.digest(ctc11, [stdlib.checkedBigNumberify('./index.rsh:394:15:dot', stdlib.UInt_max, 8), v24, v25, v32, v39, v173, v175, v177, v178, v197, v322]);

ParseVal Error With Reach

Attempted to make a reach program, but it had a parse issue.

Here is the error:

Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
Verification failed:
  when ALL participants are honest
  of theorem: while invariant after loop
  at ./index.rsh:118:3:invariant

reachc: The compiler has encountered an internal error:

  parseVal: Array(Object({"date": UInt, "inventoryUnit": UInt, "inventoryValue": UInt, "stateName": UInt, "supplyName": UInt, "transitions": Array(UInt, 10), "transitionsLength": UInt}), 10) List [Atom "_",Atom "as-array",Atom "k!38"]

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:73:3 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Util
  impossible, called at src/Reach/Verify/SMT.hs:467:10 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Verify.SMT

Here is the gist of the code that generated the issue:
https://gist.github.com/jboetticher/33dffa61b5904a887421ab86dd7f3dd3

Follow your own docker-compose.yml conventions consistently

reach scaffold generates a docker-compose.yml file that contains inconsistencies regarding naming and ordering conventions that had been established prior to the addition of Conflux. Whether you stick to the old conventions or change to new ones, I recommend that you choose and follow your own conventions in order to help developers understand this file quickly. Here are examples:

Current Convention: name-devnet.

Examples: ethereum-devnet and algorand-devnet.

Non-adherence: devnet-cfx.

Current Convention: List live first and then dockerized.

Examples:

reach-app-seller-and-buyer-ETH-live
reach-app-seller-and-buyer-ETH-test-dockerized-geth

reach-app-seller-and-buyer-ALGO-live
reach-app-seller-and-buyer-ALGO-test-dockerized-algod

Non-adherence:

reach-app-seller-and-buyer-CFX-devnet
reach-app-seller-and-buyer-CFX-live

Current Convention: Indicate devnet with test-dockerized.

Examples:

reach-app-seller-and-buyer-ETH-test-dockerized-geth
reach-app-seller-and-buyer-ALGO-test-dockerized-algod

Non-adherence: reach-app-seller-and-buyer-CFX-devnet.

Current Convention: Service order is Ethereum, Algorand.

Example:

ethereum-devnet:
    image: reachsh/ethereum-devnet:0.1
algorand-devnet:
    image: reachsh/algorand-devnet:0.1

reach-app-seller-and-buyer-ETH-live:
    ...
reach-app-seller-and-buyer-ALGO-live:
    ...

Non-adherence: The Conflux entries are inconsistent. The image entry appears before ethereum and algorand. The environment entry appears after ethereum and algorand.

Error "Invalid name shadowing. Identifier 't' is already bound" when nesting parallelReduce()

Issue Overview

I'm experiencing an awkward error when nesting parallelReduce(). I'm not sure whether this is expected behavior or a bug. Specifically I'm encountering Example 4, but found the same error for a different situation in Example 3.

Example 1 - passes

A non-nested PR that uses participant A in multiple cases passes verification: https://github.com/reach-sh/reach-lang/blob/master/examples/multiple-pr-case/index.rsh

Example 2 - passes

When nested PRs use different participants in their cases, the code passes verification.

'reach 0.1';

const Common = ({
  doCase: Fun([UInt], Bool) });

export const main = Reach.App(
  {}, [Participant('A', {...Common}), Participant('B', {...Common})], (A, B) => {
    A.publish()
      .pay(1);
    commit();

    B.publish();
 
    const keepGoing =
      parallelReduce(true)
        .invariant(balance() == 1)
        .while(keepGoing)
        .case(
          A,
          (() => ({ when: true })),
          ((_) => {

            const keepGoingB = 
              parallelReduce(true)
                .invariant(balance() == 1)
                .while(keepGoingB)
                .case( 
                  B,
                  (() => ({ when: declassify(interact.doCase(1)) })),
                  () => { return true; }) 
                .timeout(1000, () => {
                  Anybody.publish();
                  return false;
                });
  
            return false; 

          })
        )
        .timeout(false);

    transfer(1).to(B);
    commit();
    exit();
  }
);

Example 3 - fails

When a case on the outer PR uses the same participant as a case on the inner PR, an error is thrown: reachc: error: ./index.rsh:24:29:const: Invalid name shadowing. Identifier 't' is already bound at ./index.rsh:15:21:id. It cannot be bound again at ./index.rsh:24:29:id

'reach 0.1';

const Common = ({
  doCase: Fun([UInt], Bool) });

export const main = Reach.App(
  {}, [Participant('A', {...Common}), Participant('B', {...Common})], (A, B) => {
    A.publish()
      .pay(1);
    commit();

    B.publish();
 
    const keepGoing =
      parallelReduce(true)
        .invariant(balance() == 1)
        .while(keepGoing)
        .case(
          A,
          (() => ({ when: true })),
          ((_) => {

            const keepGoingB = 
              parallelReduce(true)
                .invariant(balance() == 1)
                .while(keepGoingB)
                .case( 
                  A,
                  (() => ({ when: declassify(interact.doCase(1)) })),
                  () => { return true; }) 
                .timeout(1000, () => {
                  Anybody.publish();
                  return false;
                });
  
            return false; 

          })
        )
        .timeout(false);

    transfer(1).to(B);
    commit();
    exit();
  }
);

Example 4 - fails

When a case on the outer PR uses participant A, and the inner PR uses participant B in multiple cases, an error is thrown: reachc: error: ./index.rsh:24:29:application: Invalid name shadowing. Identifier 't' is already bound at ./index.rsh:15:21:id. It cannot be bound again at ./index.rsh:24:29:id. Given that examples 1 and 2 both pass verification, it seems like this should pass as well, yet it does not.

'reach 0.1';

const Common = ({
  doCase: Fun([UInt], Bool) });

export const main = Reach.App(
  {}, [Participant('A', {...Common}), Participant('B', {...Common})], (A, B) => {
    A.publish()
      .pay(1);
    commit();

    B.publish();
 
    const keepGoing =
      parallelReduce(true)
        .invariant(balance() == 1)
        .while(keepGoing)
        .case(
          A,
          (() => ({ when: true })),
          ((_) => {

            const keepGoingB = 
              parallelReduce(true)
                .invariant(balance() == 1)
                .while(keepGoingB)
                .case( 
                  B,
                  (() => ({ when: declassify(interact.doCase(1)) })),
                  () => { return true; }) 
                .case( 
                  B,
                  (() => ({ when: declassify(interact.doCase(2)) })),
                  () => { return true; }) 
                .timeout(1000, () => {
                  Anybody.publish();
                  return false;
                });
  
            return false; 

          })
        )
        .timeout(false);

    transfer(1).to(B);
    commit();
    exit(); 
  }
);

Tutorial 8 does not run on Algorand test image

At first I thought I had made a mistake when following the tutorial found at https://docs.reach.sh/tut-8.html but it appears there may be something going on in the image.

Steps to reproduce:

  • copy package.json, Makefile, index.rsh, index.mjs, docker-compose.yml, Dockerfile into a directory
  • move &default-app from reach-app-tut-8-ETH-test-dockerized-geth to reach-app-tut-8-ALGO-test-dockerized-algod
  • run ./reach compile
  • run make build
  • run make run-alice

Output is as follows:

MacBook-Pro-6:tut $ make run-alice
docker-compose run --rm alice
Starting tut_algorand-postgres-db_1 ... done
Starting tut_algorand-devnet_1      ... done

> @reach-sh/tut-8@ index /app
> node --experimental-modules --unhandled-rejections=strict index.mjs

(node:18) ExperimentalWarning: The ESM module loader is experimental.
Are you Alice?
y
Starting Rock, Paper, Scissors! as Alice
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
y
/stdlib/node_modules/algosdk/src/transaction.js:181
      throw Error(
            ^

Error: Application global byte slices count must be a positive number and smaller than 2^53-1
    at new Transaction (/stdlib/node_modules/algosdk/src/transaction.js:181:13)
    at Object.makeApplicationCreateTxn (/stdlib/node_modules/algosdk/src/makeTxn.js:930:10)
    at deployP (file:///stdlib/ALGO.mjs:975:86)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @reach-sh/tut-8@ index: `node --experimental-modules --unhandled-rejections=strict index.mjs`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the @reach-sh/tut-8@ index script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

I tried to find some information about what is happening but I don't know much about Algorand at this point. The best I could do was this PyTeal Docs page, explaining the global_num_byte_slices enum which matches the error message https://pyteal.readthedocs.io/en/latest/api.html#pyteal.TxnField.global_num_byte_slices

Add supporting use cases for each of these programs

Description
This page describes the different programs Reach uses. Adding context to when you'd use it for each section would be very helpful I think.
For example: Under 'switch'. If you put just a sentence or two like, "You would use this in a scenario where Alice x with Bob... etc'

Page Link
https://docs.reach.sh/ref-programs-compute.html#%28tech._value._definition%29

Search String
"A switch statement, written switch (VAR) { CASE ... }, where VAR is a variable bound to..."

Issue
These programs are useful but seem to be floating in mid air. Let's spoil the developers and let them see how we use them!

Suggestion
I think these programs need some more context about when to apply them.

I believe parallelReduce fails on Ethereum.

See this video to watch a parallelReduce test that passes on Algorand and fails on Ethereum. Video includes tests specs, link to github repo, and error msg at the end. I'll show the error msg here, too:

/stdlib/node_modules/@ethersproject/logger/lib/index.js:187
        var error = new Error(message);
                    ^

Error: missing response (requestBody="{\"method\":\"eth_blockNumber\",\"params\":[],\"id\":94,\"jsonrpc\":\"2.0\"}", requestMethod="POST", serverError={"code":"ECONNRESET"}, url="http://ethereum-devnet:8545", code=SERVER_ERROR, version=web/5.3.0)
    at Logger.makeError (/stdlib/node_modules/@ethersproject/logger/lib/index.js:187:21)
    at Logger.throwError (/stdlib/node_modules/@ethersproject/logger/lib/index.js:196:20)
    at /stdlib/node_modules/@ethersproject/web/lib/index.js:213:36
    at step (/stdlib/node_modules/@ethersproject/web/lib/index.js:33:23)
    at Object.throw (/stdlib/node_modules/@ethersproject/web/lib/index.js:14:53)
    at rejected (/stdlib/node_modules/@ethersproject/web/lib/index.js:6:65)
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  reason: 'missing response',
  code: 'SERVER_ERROR',
  requestBody: '{"method":"eth_blockNumber","params":[],"id":94,"jsonrpc":"2.0"}',
  requestMethod: 'POST',
  serverError: Error: socket hang up
      at connResetException (internal/errors.js:607:14)
      at Socket.socketOnEnd (_http_client.js:499:23)
      at Socket.emit (events.js:388:22)
      at endReadableNT (internal/streams/readable.js:1336:12)
      at processTicksAndRejections (internal/process/task_queues.js:82:21) {
    code: 'ECONNRESET'
  },
  url: 'http://ethereum-devnet:8545'

Webpack 5: Unable to import @reach-sh/stdlib

The error seems to be cause by Webpack 5 not being able to resolve the imports within a .mjs file.

Related issue: webpack/webpack#11467

Attempted suggested solution with no success: webpack/webpack#11467 (comment)

Webpack Config File

/* eslint-disable */
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
require('dotenv').config()

module.exports = {
  mode: 'development',
  entry: {
    index: './src/index.js',
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
    publicPath: '/'
  },
  devServer: {
    port: process.env.DEV_PORT,
    watchContentBase: true
  },
  resolve: {
    extensions: ['.js', '.ts', '.mjs', '.json', '.wasm']
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader']
      },
      {
        test: /\.m?js/,
        resolve: {
          fullySpecified: false
        }
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin()
  ],
}

Error message:

vsh in ~/Documents/github/crypto/algorand/reach/battleship/client(ruby-3.0.0) on master λ npm run nodeserve

> [email protected] nodeserve
> node server.js

Battleship client development server running on port 3000...
✖ 「wdm」: assets by chunk 3.39 MiB (name: index)
  asset index.bundle.js 3.39 MiB [emitted] (name: index)
  asset index.css 21 bytes [emitted] (name: index)
asset 10fe4030c4f3a48a7c95.png 6.42 KiB [emitted] [immutable] [from: src/assets/battleship.png] (auxiliary name: index)
asset index.html 376 bytes [emitted]
Entrypoint index 3.39 MiB (6.42 KiB) = index.css 21 bytes index.bundle.js 3.39 MiB 1 auxiliary asset
orphan modules 2.27 KiB [orphan] 8 modules
runtime modules 1.31 KiB 8 modules
modules by path ./node_modules/ 2.93 MiB 265 modules
modules by path ./src/ 4.41 KiB (javascript) 6.42 KiB (asset) 20 bytes (css/mini-extract)
  javascript modules 4.31 KiB
    ./src/index.js 252 bytes [built] [code generated] [1 warning]
    ./src/App.js 4.02 KiB [built] [code generated] [1 warning]
    ./src/App.css 50 bytes [built] [code generated]
  modules by path ./src/assets/ 99 bytes (javascript) 6.42 KiB (asset)
    ./src/assets/battleship.png 42 bytes (javascript) 6.42 KiB (asset) [built] [code generated]
    ./src/assets/game-description.json 57 bytes [built] [code generated]
  css ./node_modules/css-loader/dist/cjs.js!./src/App.css 20 bytes [code generated]
buffer (ignored) 15 bytes [optional] [built] [code generated]
crypto (ignored) 15 bytes [built] [code generated]
./util.inspect (ignored) 15 bytes [built] [code generated]

WARNING in ./src/App.js
Module Warning (from ./node_modules/eslint-loader/dist/cjs.js):

/Users/vsh/Documents/github/crypto/algorand/reach/battleship/client/src/App.js
   6:8  warning  Missing space before function parentheses  space-before-function-paren
  15:9  warning  Missing space before function parentheses  space-before-function-paren

✖ 2 problems (0 errors, 2 warnings)
  0 errors and 2 warnings potentially fixable with the `--fix` option.

 @ ./src/index.js 4:0-24 6:50-53

WARNING in ./src/index.js
Module Warning (from ./node_modules/eslint-loader/dist/cjs.js):

/Users/vsh/Documents/github/crypto/algorand/reach/battleship/client/src/index.js
  1:8   warning  'React' is defined but never used  no-unused-vars
  3:13  warning  'reach' is defined but never used  no-unused-vars
  4:8   warning  'App' is defined but never used    no-unused-vars

✖ 3 problems (0 errors, 3 warnings)


ERROR in ./node_modules/@reach-sh/stdlib/ALGO.mjs 582:10-24
export 'default' (imported as 'msgpack') was not found in '@msgpack/msgpack' (possible exports: DataViewIndexOutOfBoundsError, DecodeError, Decoder, EXT_TIMESTAMP, Encoder, ExtData, ExtensionCodec, decode, decodeArrayStream, decodeAsync, decodeMulti, decodeMultiStream, decodeStream, decodeTimestampExtension, decodeTimestampToTimeSpec, encode, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, encodeTimestampExtension)
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO.mjs 613:10-24
export 'default' (imported as 'msgpack') was not found in '@msgpack/msgpack' (possible exports: DataViewIndexOutOfBoundsError, DecodeError, Decoder, EXT_TIMESTAMP, Encoder, ExtData, ExtensionCodec, decode, decodeArrayStream, decodeAsync, decodeMulti, decodeMultiStream, decodeStream, decodeTimestampExtension, decodeTimestampToTimeSpec, encode, encodeDateToTimeSpec, encodeTimeSpecToTimestamp, encodeTimestampExtension)
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO.mjs 895:17-38
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO.mjs 1140:13-34
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 11:18-34
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 30:18-38
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 30:39-60
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 34:11-32
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 39:18-42
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 40:20-45
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 44:18-39
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 45:20-40
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 81:11-30
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 99:11-30
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 118:11-30
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 141:13-32
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/ALGO_compiled.mjs 175:13-32
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 17:0-103 19:43-57 373:46-60 374:127-135 643:9-21 927:51-65 978:94-108 1022:28-42 1035:76-90 1233:9-23 1235:27-41
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/CBR.mjs 2:18-34
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/shared.mjs 3:0-60 5:0-43 5:0-43 110:13-25 138:37-49 143:15-27 161:28-40 161:47-59 164:30-42 164:50-62 165:30-42 165:50-62 166:30-42 166:50-62 167:30-42 167:50-62 168:30-42 168:50-62 171:28-40 171:48-60 172:28-40 172:47-59 173:28-40 173:48-60 174:28-40 174:47-59 199:77-89 200:31-43
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/CBR.mjs 32:18-39
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/shared.mjs 3:0-60 5:0-43 5:0-43 110:13-25 138:37-49 143:15-27 161:28-40 161:47-59 164:30-42 164:50-62 165:30-42 165:50-62 166:30-42 166:50-62 167:30-42 167:50-62 168:30-42 168:50-62 171:28-40 171:48-60 172:28-40 172:47-59 173:28-40 173:48-60 174:28-40 174:47-59 199:77-89 200:31-43
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/CBR.mjs 88:16-40
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/shared.mjs 3:0-60 5:0-43 5:0-43 110:13-25 138:37-49 143:15-27 161:28-40 161:47-59 164:30-42 164:50-62 165:30-42 165:50-62 166:30-42 166:50-62 167:30-42 167:50-62 168:30-42 168:50-62 171:28-40 171:48-60 172:28-40 172:47-59 173:28-40 173:48-60 174:28-40 174:47-59 199:77-89 200:31-43
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 1:0-28
Module not found: Error: Can't resolve 'crypto' in '/Users/vsh/Documents/github/crypto/algorand/reach/battleship/client/node_modules/@reach-sh/stdlib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
	- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
	- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
	resolve.fallback: { "crypto": false }
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 4:0-24
Module not found: Error: Can't resolve 'util' in '/Users/vsh/Documents/github/crypto/algorand/reach/battleship/client/node_modules/@reach-sh/stdlib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
	- add a fallback 'resolve.fallback: { "util": require.resolve("util/") }'
	- install 'util'
If you don't want to include a polyfill, you can use an empty module like this:
	resolve.fallback: { "util": false }
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 64:60-72
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 65:18-34
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 134:12-34
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/@reach-sh/stdlib/shared.mjs 145:15-38
export 'default' (imported as 'ethers') was not found in 'ethers' (possible exports: BaseContract, BigNumber, Contract, ContractFactory, FixedNumber, Signer, VoidSigner, Wallet, Wordlist, constants, errors, ethers, getDefaultProvider, logger, providers, utils, version, wordlists)
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 14:0-168 20:0-29 20:0-29 80:6-11 84:4-9 92:2-7 102:2-7 112:4-9 122:2-7 125:4-9 129:4-9 298:77-89 301:4-9 351:2-7 358:2-7 375:41-51 396:2-7 400:2-7 479:22-32 483:30-40 548:45-55 557:17-34 559:102-119 566:18-30 580:4-9 581:4-9 582:4-9 602:4-9 604:4-9 605:4-9 611:4-9 612:4-9 613:4-9 624:2-7 640:4-9 649:33-45 665:6-11 670:25-34 671:33-42 675:14-26 685:6-11 689:6-11 695:6-11 701:10-15 703:12-17 707:8-13 712:20-32 737:12-18 748:8-13 749:8-14 752:92-104 754:8-13 766:8-13 768:8-13 775:8-13 777:8-13 800:10-15 812:8-13 817:10-15 820:12-17 822:12-17 846:6-11 875:8-13 886:8-13 888:8-13 894:10-15 897:8-13 900:8-13 901:24-33 902:8-13 905:8-13 908:8-13 911:8-13 920:16-28 926:37-49 929:6-11 936:8-13 943:8-13 945:8-13 947:8-13 949:8-13 957:17-34 958:6-11 960:6-11 965:6-11 967:6-11 970:8-13 973:8-13 977:21-35 982:4-9 1019:4-9 1024:11-24 1027:11-24 1043:9-21 1069:21-32 1072:9-21 1076:30-42 1093:23-35 1108:6-11 1111:6-11 1158:42-54 1163:4-9 1165:18-30 1168:2-7 1173:2-7 1194:2-7 1204:6-11 1210:2-7
 @ ./src/index.js 3:0-51

ERROR in ./node_modules/wait-port/lib/wait-port.js 2:12-26
Module not found: Error: Can't resolve 'net' in '/Users/vsh/Documents/github/crypto/algorand/reach/battleship/client/node_modules/wait-port/lib'
 @ ./node_modules/@reach-sh/stdlib/waitPort.mjs 1:0-36 22:8-19
 @ ./node_modules/@reach-sh/stdlib/ALGO.mjs 15:0-38 34:15-23
 @ ./src/index.js 3:0-51

3 errors have detailed information that is not shown.
Use 'stats.errorDetails: true' resp. '--stats-error-details' to show it.

webpack 5.37.1 compiled with 27 errors and 2 warnings in 2333 ms
ℹ 「wdm」: Failed to compile.

Error on Remote Solidity Smart Contract

I had released a bug report on this. It was fixed and now the issue has returned.

{"contracts":{"index.sol:DaiToken":{"abi":"[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"remaining","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]","bin":"60c0604052600e60808190526d26b7b1b5902220a4902a37b5b2b760911b60a090815261002f916000919061009c565b50604080518082019091526004808252636d44414960e01b602090920191825261005b9160019161009c565b5069d3c21bcecceda10000006002556003805460ff1916601217905534801561008357600080fd5b506002543360009081526004602052604090205561013d565b828054600181600116156101000203166002900490600052602060002090601f0160209004810192826100d25760008555610118565b82601f106100eb57805160ff1916838001178555610118565b82800160010185558215610118579182015b828111156101185782518255916020019190600101906100fd565b50610124929150610128565b5090565b5b808211156101245760008155600101610129565b61063f8061014c6000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063324536eb11610071578063324536eb1461020a5780635c6581651461021257806370a082311461024057806395d89b4114610266578063a9059cbb1461026e578063dd62ed3e1461029a576100b4565b806306fdde03146100b9578063095ea7b31461013657806318160ddd1461017657806323b872dd1461019057806327e235e3146101c6578063313ce567146101ec575b600080fd5b6100c16102c8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100fb5781810151838201526020016100e3565b50505050905090810190601f1680156101285780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101626004803603604081101561014c57600080fd5b506001600160a01b038135169060200135610356565b604080519115158252519081900360200190f35b61017e6103bc565b60408051918252519081900360200190f35b610162600480360360608110156101a657600080fd5b506001600160a01b038135811691602081013590911690604001356103c2565b61017e600480360360208110156101dc57600080fd5b50356001600160a01b03166104a1565b6101f46104b3565b6040805160ff9092168252519081900360200190f35b61017e6104bc565b61017e6004803603604081101561022857600080fd5b506001600160a01b03813581169160200135166104c2565b61017e6004803603602081101561025657600080fd5b50356001600160a01b03166104df565b6100c16104fa565b6101626004803603604081101561028457600080fd5b506001600160a01b038135169060200135610554565b61017e600480360360408110156102b057600080fd5b506001600160a01b03813581169160200135166105de565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561034e5780601f106103235761010080835404028352916020019161034e565b820191906000526020600020905b81548152906001019060200180831161033157829003601f168201915b505050505081565b3360008181526005602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b6001600160a01b0383166000908152600460205260408120548211156103e757600080fd5b6001600160a01b038416600090815260056020908152604080832033845290915290205482111561041757600080fd5b6001600160a01b0380851660008181526004602090815260408083208054889003905593871680835284832080548801905583835260058252848320338452825291849020805487900390558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b60046020526000908152604090205481565b60035460ff1681565b60025481565b600560209081526000928352604080842090915290825290205481565b6001600160a01b031660009081526004602052604090205490565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561034e5780601f106103235761010080835404028352916020019161034e565b3360009081526004602052604081205482111561057057600080fd5b336000818152600460209081526040808320805487900390556001600160a01b03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b6001600160a01b0391821660009081526005602090815260408083209390941682529190915220549056fea264697066735822122069b843f35deddce2866f47f91b1f8e6f8ae4355079f426093b065fb8146a7b8864736f6c63430007040033"}},"version":"0.7.4+commit.3f05b770.Darwin.appleclang"}file:///app/index.mjs:21 const remoteABI = remoteCtc["abi"]; ^
TypeError: Cannot read property 'abi' of undefined at file:///app/index.mjs:21:30

Inquiry on adding support for apple silicon

Issue description

I followed basic steps in https://docs.reach.sh/tut-2.html after running reach run I get the following set of logs:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
make: *** [build/index.main.mjs] Error 137

Hardware info

OS Version : macOS Big Sur 11.4
Chip: Apple M1

Further notes

Would appreciate any feedback input on this, I suspect it has something to do with the M1 chip itself, running identical set of steps on an intel based Mac works without any issues. Thanks in advance for any replies!

Compiler internal error: getIllegalModeSuggestion

The attached code below will yield the following :

reachc: The compiler has encountered an internal error:

  getIllegalModeSuggestion

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:66:3 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Util
  impossible, called at src/Reach/Eval/Error.hs:254:12 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Eval.Error

Thank you.


Code:

'reach 0.1';
'use strict';

//-----------------------------------------------------------------------------
// Token operative & compliance parameters
//-----------------------------------------------------------------------------

const TokenParameters = Object({
  maxTransfers: UInt,
})

//-----------------------------------------------------------------------------
// Interaction interfaces
//-----------------------------------------------------------------------------

const IManager = {
  getBootstrapParams: Fun([], Tuple(Token, TokenParameters)),
  setupComplete: Fun([], Null),
  shouldStop: Fun([], Bool)
}

const ISender = {
  getAxfer: Fun([], Maybe(Tuple(UInt, Address)))
}


//-----------------------------------------------------------------------------
// Helper functions
//-----------------------------------------------------------------------------
function validateParams(params) {
  assume(params.maxTransfers > 0);
}

//-----------------------------------------------------------------------------
// DApp Entry point
//-----------------------------------------------------------------------------
export const main = Reach.App(
  {
    deployMode: 'constructor'
  }, [
  Participant('Manager', IManager),
  Participant('Sender', ISender)
],
  (Manager, Sender) => {

    // Step1:Manager must set token parameters

    Manager.only(() => {
      const [token, params] = declassify(interact.getBootstrapParams());
      validateParams(params);
      interact.setupComplete();
    })
    Manager.publish(token, params);
    commit();

    Sender.publish();

    const run = parallelReduce(true)
      .invariant(balance() == 0 && balance(token) == 0)
      .while(run)
      .case(Manager,
        (() => ({ when: declassify(interact.shouldStop()) })),
        ((_) => 0),
        () => { return false }
      )
      .case(Sender,
        (() => {
          const axferParams = declassify(interact.getAxfer());
          return {
            msg: fromSome(axferParams, [0, this]),
            when: isSome(axferParams)
          }
        }),
        ((axferParams) => {
          const amount = axferParams[0];
          assume(amount > 0, "EZERO");
          return [amount, token]
        }),
        ((axferParams) => {
          const amount = axferParams[0];
          const rcvAddr = axferParams[1];
          transfer(amount, token).to(rcvAddr);
          return true;
        })
      )
  }
);

stdlib.hasRandom in tutorials

Starting with Tutorial 5, frontends spread stdlib.hasRandom into Player objects:

const Player = (Who) => ({
  ...stdlib.hasRandom,
  getHand: async () => {const hand = Math.floor(Math.random() * 3);
  etc. 
});

The inclusion of stdlib.hasRandom has nothing to do with the subsequent use of Math.random and Math.floor as some readers might mistakenly conclude. The only reason I can see to include stdlib.hasRandom in frontend Player objects (in this case) is to make stdlib.hasRandom.random() available to makeCommitment in the backend. If I am correct (never a sure thing) then this is like a patient bringing a stethoscope to a doctor's visit: the Dr should already have all needed equipment, and makeCommitment should take care of internal processing needs without the frontend supplying stdlib.hasRandom.random().

I admit, there may be other reasons for frontends to supply stdlib.hasRandom in the tutorials that I don't understand. If so, apologies!

Internal Compiler Error

Issue

  • Compiler seems mad about my use of an Array in a while loop
    • The array is received from the front-end, and is assumed to contain Addresses
    • No compilation error when the general logic is replicated in a parallelReduce

Error (full output)

Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
Verification failed:
  when ALL participants are honest
  of theorem: assert
  msg: "balance zero at application exit"
  at ./index.rsh:74:7:application

reachc: The compiler has encountered an internal error:

  parseVal: Array(Address, 2) List [List [Atom "as",Atom "const",List [Atom "Array",Atom "Int",Atom "Address"]],Atom "Address!val!0"]

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:73:3 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Util
  impossible, called at src/Reach/Verify/SMT.hs:467:10 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Verify.SMT

Application Code

"reach 0.1";

const AuctionProps = {
  arbitrator: Array(Address, 2),
  assetId: Token,
  price: UInt,
  quantity: UInt,
};

const BuyerProps = {
  getPurchaseAmount: Fun([UInt, UInt], UInt),
  showSaleItem: Fun([], Null),
};

const OwnerInterface = {
  getSaleProps: Fun([], Object(AuctionProps)),
  ...BuyerProps,
};

export const main = Reach.App(() => {
  const Owner = Participant("Owner", OwnerInterface);
  const Buyer = ParticipantClass("Buyer", BuyerProps);
  deploy();

  // Set up sale-item details
  Owner.only(() => {
    const sale = declassify(interact.getSaleProps());
    const token = sale.assetId;
  });
  // Pay token to contract
  Owner.publish(sale, token).pay([[sale.quantity, token]]);
  commit();

  Buyer.publish();

  var inStock = sale.quantity;
  invariant(balance(token) == inStock);
  while (inStock > 0) {
    commit();

    Buyer.only(() => {
      // Show what's on sale (allows the front-end to use vNFTSale)
      interact.showSaleItem();
      const qty = declassify(interact.getPurchaseAmount(inStock, sale.price));
      assume(qty > 0, "You need to purchase at least 1 item!");
      const buyerPmt = qty * sale.price;
      assume(qty <= inStock, "There aren't that many items left!");
    });

    // Only attempt to purchase when buyer wants more than 0 items
    Buyer.publish(qty, buyerPmt)
      .when(buyerPmt > 0)
      .pay(buyerPmt)
      .timeout(false);

    // Transfer quantity of purchased NFTs to buyer
    transfer(qty, token).to(this);

    // Payout participants => This is likely where the rage occurs.
    // The exact same chunk works in a `parallelReduce`

    const arbFee = (buyerPmt * (2 / 100)) / Array.length(sale.arbitrator);
    Array.forEach(sale.arbitrator, (a) => {
      transfer(arbFee).to(a);
    });
    transfer(balance()).to(Owner);

    // Update number of items left to sell
    const inventory = inStock - qty;
    inStock = inventory;
    continue;
  }

  commit();
  exit();
});

Docs: Reach init adds // ... to default index.rsh script

Description

  • Confusing use of ellipses in the index.rsh file.

Page Link

  • NA, this is not reflected in our documentation, but it appears in the actual index.rsh script.

Search String

  • " // ..."

Issue

  • When we spin up a new script using ./reach init, it automatically adds "// ..." in it on Line 6. This was very confusing to me in the beginning b/c "..." is actually used in Javascript as a rest operator so it makes me think I missed a critical step. It is not needed here. According to Matt Audesse, "// ..." is intended to be read as "yada yada yada, so on and so forth".

::  issue

Suggestion

  • I think remove the ellipses and add an actual sentence instead.

Compiler error: [Participant] is bound and cannot be rebound in parallelReduce loop

The following parallelReduce loop will yield

reachc: error: ./registry.rsh:23:41:application: Administrator is bound and cannot be rebound
'reach 0.1'
'use strict'

const IAdministrator = {
    getNewEntry: Fun([],Address),
    shouldStop: Fun([], Bool)
}

const IRegistryView = {
    last: UInt
}

export const main = Reach.App({
    deployMode: "constructor" 
    },
    [ Participant('Administrator', IAdministrator),
      View('RegistryView', IRegistryView) ], 
     (Admin, RegistryView) => {
        Admin.publish();
        
        const registry = new Set()

        const isRunning = parallelReduce(true)
            .invariant(balance () == 0)  // No funds movement, should validate always
            .while(isRunning)
            .case(
                Admin,
                /* publish_expr */
                (() => ({ when: declassify(interact.shouldStop()) })),
                /* pay_expr */
                ((_) => 0),
                /* consensus_expr */
                (() => {
                    return false;
                })
            )
            .case(
                Admin,
                /* publish_expr */
                (() => ({ msg: declassify(interact.getNewEntry()) })),
                /* pay_expr */
                ((_) => 0),
                /* consensus_expr */
                ((addr) => {
                    registry.insert(addr);
                    return isRunning;
                })
            )

        commit();
    })
    

Thanks in advance.

Tell user to cd to workshop folder

In workshops 1-5, the directions tell the user to mkdir the workshop directory, and then, assuming that the user has changed directory into the new directory, the directions tell the user to run ../reach version to verify that the script will run. Perhaps we should be more explicit so that copy/paste users don't get tripped up.

Tutorial 2.1 avoids this confusion by using mkdir -p ~/reach/tut && cd ~/reach/tut. This approach is probably the most bang for the least buck. This involves a change to lib-rkt.

Another approach might be to use ~/reach/reach throughout.

One more idea to consider: Currently, reach-lang has a particular directory structure. I can git clone it to my computer, cd to any tutorial or workshop, and run the example using ~/reach-lang/reach. I can add same to my path variable. I can also set my VSCode Reach IDE extension Executable Location variable to same. We could use this same directory structure for our "learning" directory structure, but change the root directory name from reach-lang to something else. We could choose reach-learn, but I think it is too similar to reach-lang. A better choice, perhaps, might be reach-study. Thx.

Compiler error: Stack too deep when compiling inline assembly: Variable dataEnd is 2 slot(s) too deep inside the stack.

Experiencing the following on ./reach run, although all theorums appear to be passing. I'm sure there are issues with the test front end since I just finished mocking up the initial draft, but not sure whether or not that shoud/would affect compilation. I should note that I'm seeing the same whether the MAX_XYZ constants are >= 1.

Error/CallStack

Compiler error: Stack too deep when compiling inline assembly: Variable dataEnd is 2 slot(s) too deep inside the stack.

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:73:3 in reach-0.1.2-8gxBL61FkZIAAO2AD266di:Reach.Util
  impossible, called at src/Reach/Connector/ETH_Solidity.hs:1368:17 in reach-0.1.2-8gxBL61FkZIAAO2AD266di:Reach.Connector.ETH_Solidity
make: *** [Makefile.index:8: build/index.main.mjs] Error 1

reach.sh

"reach 0.1";

// ========================================================
// Constants
// ========================================================

// Since reach cannot really handle floating point numbers.
const BAKESALE_FEE_PERCENT = 5; 
const BAKESALE_FEE_MULTIPLE = BAKESALE_FEE_PERCENT / 100;

const MAX_BENEFICIARIES_PER_ITEM = 1;
const MAX_LINE_ITEMS_PER_MERCHANT = 1;
const MAX_TOTAL_MERCHANTS = 1;

// ========================================================
// Primary Objects & Their Fakers
// ========================================================

/**
 * Create an "isReal" version of an object.
 * 
 * @param {object} x
 *   The object to clarify as real. 
 * @param {bool} state
 *   Whether or not the object is real.
 * @returns {object}
 *   The initial object with an isReal prop added.
 */
 const createIsReal = (state, x) => ({
  isReal: state,
  ...x
});

/**
 * The beneficiary of a particular item.
 */
const Beneficiary = {
  isReal: Bool,
  addr: Address,
  percentToReceive: UInt,
};

/**
 * Create a fake benficiary.
 * 
 * @param addr
 *   The fake address. 
 * @returns 
 *   The fake Beneficiary.
 */
const createFakeBeneficiary = (addr) => {
  return createIsReal(false, {
    addr,
    percentToReceive: 0}
  );
}

/**
 * An order line item.
 */
const LineItem = {
  isReal: Bool,
  totalCost: UInt, // The unit price * qty
  shipping: UInt,
  tax: UInt,
  beneficiaries: Array(Maybe(Object(Beneficiary)), MAX_BENEFICIARIES_PER_ITEM)
}

/**
 * Create a fake LineItem.
 * 
 * @param addr
 *   The fake address.
 * @returns 
 *   The fake LineItem.
 */
const createFakeLineItem = (addr) => {
  const beneficiaries = Array.iota(MAX_BENEFICIARIES_PER_ITEM).map((_) =>  Maybe(Object(Beneficiary)).Some(createFakeBeneficiary(addr)));

  return createIsReal(false, {
    totalCost: 0,
    shipping: 0,
    tax: 0,
    beneficiaries
  });
}

/**
 * Array of order line items for a particular merchant.
 */
const Merchant = {
  isReal: Bool,
  addr: Address,
  lineItems: Array(Maybe(Object(LineItem)), MAX_LINE_ITEMS_PER_MERCHANT) 
}

/**
 * Create a fake Merchants.
 * 
 * @param addr
 *   The fake address. 
 * @returns 
 *   The fake Merchants obj.
 */
 const createFakeMerchants = (addr) => {
  assert(addr !== null)
 
  return createIsReal(false, { 
    addr,
    lineItems: Array.iota(MAX_LINE_ITEMS_PER_MERCHANT).map(_ => Maybe(Object(LineItem)).Some(createFakeLineItem(addr)))
    // lineItems: []
  }); 
 } 

/**
 * The order data for which payment is processed.
 */
const OrderData = {
  orderTotal: UInt,
  merchantItems: Array(Maybe(Object(Merchant)), MAX_TOTAL_MERCHANTS),
}


// ========================================================
// Laundromat
// ========================================================

/**
 * Convert Array(Maybe(Object(Beneficiary)) to usable Array(Object(Beneficiary)).
 * 
 * @param {Array(Maybe(Object(Beneficiary))} beneficiaries
 *   The array of maybe beneficiaries.
 * @param addr 
 *   The address to be used for the fakes.
 * @returns {Array(Object(Beneficiary)}
 *   Array of usable beneficiaries.
 */
 const cleanBeneficiaries = (beneficiaries, addr) => {
  return beneficiaries.map((x) => {
    return fromMaybe(x,
      (() => createFakeBeneficiary(addr)), 
      ((y) => createIsReal(true, y))
    ); 
  })
}

/**
 * Convert Array(Maybe(Object(LineItem)) to usable Array(Object(LineItem)).
 * 
 * @param {Array(Maybe(Object(LineItem))} lis
 *   The array of maybe line items..
 * @param addr 
 *   The address to be used for the fakes.
 * @returns {Array(Object(LineItem)}
 *   Array of usable line items.
 */
const cleanLineItems = (lis, addr) => {
  return lis.map((x) => {
    return fromMaybe(x,
      (() => createFakeLineItem(addr)), 
      ((y) => createIsReal(true, y))
    ); 
  })
}

/**
 * Convert Array(Maybe(Object(Merchant)) to usable Array(Object(Merchant)).
 * 
 * @param {Array(Maybe(Object(Merchant))} m
 *   The array of maybe merchants.
 * @param addr 
 *   The address to be used for the fakes.
 * @returns {Array(Object(Merchant)}
 *   Array of usable merchants.
 */
const cleanMerchants = (m, addr) => {
  return m.map((x) => { 
    return fromMaybe(x,
      (() => createFakeMerchants(addr)), 
      ((y) => createIsReal(true, y))
    ); 
  })
}

/**
 * Clean the entire orderData's tree.
 * 
 * @param {OrderData} orderData
 *   The order data to be cleaned. 
 * @param {Address} fakesAddr 
 *   The address to be used for fakes.
 * 
 * @returns {OrderData} 
 *   The cleaned OrderData. 
 */
const cleanOrderData = (orderData, fakesAddr) => {
  const merchantItemsClean = cleanMerchants(orderData.merchantItems, fakesAddr);
  const merchantItemsFinal = merchantItemsClean.map(x => {
    
    // Cleaning LineItems for single Merchant 
    const lineItemsClean = cleanLineItems(x.lineItems, fakesAddr);
    const lineItemsFinal = lineItemsClean.map(y => {
      
      // Cleaning Benficiaries for a single LineItem 
      const beneficiariesClean = cleanBeneficiaries(y.beneficiaries, fakesAddr);

      return {
        isReal: y.isReal,
        totalCost: y.totalCost,
        shipping: y.shipping,
        tax: y.tax,
        beneficiaries: beneficiariesClean
      }
    });
     
    return { 
      isReal: x.isReal,
      addr: x.addr,
      lineItems: lineItemsFinal
    }
  }); 

  return {
    orderTotal: orderData.orderTotal,
    merchantItems: merchantItemsFinal 
  }
}


// ========================================================
// Order Validation
// ========================================================

/**
 * Check whether or not the order is valid to be processed.
 * 
 * @todo Check that no merchants appear more than once.
 * 
 * @param {OrderData} orderData
 *   The CLEANED order data. The logic assumes that all
 *   objects are operable, i.e. no Maybes.
 */
const validateCleanOrder = (orderData) => {
  const positiveOrderTotal = orderData.orderTotal > 0;
  const orderTotalCalcd = orderData.merchantItems.reduce(0, (oTotal, x) => {
    const merchantTotal = x.lineItems.reduce(0, (mTotal, y) => mTotal + y.totalCost);
    return oTotal + merchantTotal;
  });

  // Ensure that the provided order total matches the order contents.
  const orderTotalsMatch = positiveOrderTotal == orderTotalCalcd;

  // All amounts on the order must be >= 0.
  const allAmtsNonNegative = orderData.merchantItems.reduce(true, (allAmtsPos, x) => {
    const itemsPositive = x.lineItems.reduce(true, (ip, y) => {
      const totalCostValid = y.isReal ? y.totalCost > 0 : y.totalCost == 0
      const shippingValid = y.isReal ? y.shipping >= 0 : y.shipping == 0
      const taxValid = y.isReal ? y.tax >= 0 : y.tax == 0
      return !ip ? false : totalCostValid && shippingValid && taxValid
    });

    return !allAmtsPos ? false : itemsPositive;
  });

  // Any individual item's beneficiary percentages need to be <= 100.
  const beneficiaryPctsValid = orderData.merchantItems.reduce(true, (pctsValid, x) => {
    const itemPctsValid = x.lineItems.reduce(true, (itemPctValid, y) => {
      const beneficiariesPct = y.beneficiaries.reduce(0, (pctTotal, z) => {
        return pctTotal + z.percentToReceive;
      });
      
      return !itemPctValid ? false : beneficiariesPct <= 100;
    });
 
    return !pctsValid ? false : itemPctsValid;
  });

  // Any individual items' tax + shipping must be less than the order item's totalCost.
  // If they exceed it then that means the total does not account for one of them.
  const taxShippingValid = orderData.merchantItems.reduce(true, (tsValid, x) => {
    const itemTsValid = x.lineItems.reduce(true, (itemTsValid, y) => {      
      return y.totalCost > y.tax + y.shipping;
    });

    return !tsValid ? false : itemTsValid;
  });

  const orderIsValid = orderTotalsMatch 
    && allAmtsNonNegative
    && beneficiaryPctsValid
    && taxShippingValid;

  return {
    orderIsValid,
    orderTotalsMatch, 
    allAmtsNonNegative,
    beneficiaryPctsValid,
    taxShippingValid
  }
}


// ========================================================
// Participant Info
// ========================================================

/**
 * Errors to present to the buyer on validation or other failure.
 */
 const errors = {
  // errorInvalidOrderTotal: Fun([], Null),
  // errorAmountsExceedBalance: Fun([], Null),
  // errorInvalidRecipientAmounts: Fun([], Null),
  errorGenericInvalidOrder: Fun([], Null),
}
 
/**
 * The Buyer Interface.
 */
const BuyerInterface = {  
  getOrderData: Fun([], Object(OrderData)),
  // alertPaidRecipient: Fun([Address, UInt, Bytes], Null),
  ...errors,
};
 
// ========================================================
// Main Contract Logic
// ========================================================

export const main = Reach.App(
  {}, [ 
    ParticipantClass('Buyer', BuyerInterface),
    Participant('Bakesale', {}),
  ],
  (Buyer, Bakesale) => {
    Bakesale.publish();

    const keepGoing = 
      parallelReduce(true)
        .invariant(balance() == balance())
        .while(keepGoing)
        .case(Buyer,
          (() => {
            const orderData = declassify(interact.getOrderData());
            const orderDataClean = cleanOrderData(orderData, Bakesale);
            const validationResult = validateCleanOrder(orderDataClean);

            if(!validationResult.orderIsValid) {
              interact.errorGenericInvalidOrder();
            } 
            return {
              when: validationResult.orderIsValid
            }
          }), 
          ((_) => {
            commit();
            Buyer.only(() => {
              const orderData = declassify(interact.getOrderData());
            });
            Buyer.publish(orderData); 
            const orderDataClean = cleanOrderData(orderData, Bakesale);
            const validationResult = validateCleanOrder(orderDataClean);

            // This should never happen since we validate in the 
            // local step above, but just in case.
            if(!validationResult.orderIsValid) { 
              Buyer.only(() => declassify(interact.errorGenericInvalidOrder()));
              return true;
            } else {
              commit();
              Buyer.publish().pay(orderTotal);

              // Keep this all simple for MVP testing.
              // We can make the transfers more efficient
              // and aggregated after we know it works.
              orderDataClean.merchantItems.forEach(mi => {
                // Looking at a single merchant.
                if(mi.isReal) {
                  mi.lineItems.forEach(li => {
                    // Looking at a single line item.
                    if(li.isReal) {
                      const serviceFee = li.totalCost * BAKESALE_FEE_MULTIPLE;
                      const totalMinusFee = li.totalCost - serviceFee;

                      transfer(serviceFee).to(Bakesale);
                      // Buyer.interact(declassify(interact.alertPaidRecipient(Bakesale, serviceFee, 'service fee')))

                      /** @todo This needs to go to a tax acct. */
                      transfer(li.tax).to(Bakesale)

                      const pctToBeneficiaries = li.beneficiaries.reduce(0, (pct, x) => {
                        return pct + x.percentToReceive;
                      });

                      // Pay out the merchant.
                      const pctToMerchant = (100 - pctToBeneficiaries) / 100;
                      const amtToMerchant = pctToMerchant * totalMinusFee;
                      transfer(amtToMerchant).to(mi.addr);

                      // Pay out the beneficiaries
                      li.beneficiaries.forEach(ben => {
                        if(ben.isReal) {
                          const amtToBen = totalMinusFee * ben.percentToReceive;
                          transfer(amtToBen).to(ben);
                        }
                      })
                    }
                  })
                }
              });

              assert(balace() == 0)

              return true;
            } 

          })
        )
        // Sufficiently long timeout that it will never be
        // executed since the contract needs to be persistent.
        .timeout(100^100, () => {
          Anybody.publish();
          return true;
        }); 
    
    if(balance() > 0) {
      // Not sure how we'd ever end up with a balance here, 
      // but for now just transfer the remaining balance.
      // We need to fix this so that it tracks the last buyer
      // since it seems like they'd be the most likely source 
      // of these orphan funds?
      transfer(balance()).to(Bakesale);
    }

    commit();
  }
);

index.mjs

import {loadStdlib} from '@reach-sh/stdlib';
import * as backend from './build/index.main.mjs';

// Maximums allowed by the contract.
// This will exist in the final version.
const MAX_BENEFICIARIES_PER_ITEM = 5;
const MAX_LINE_ITEMS_PER_MERCHANT = 10;
const MAX_TOTAL_MERCHANTS = 5

// Used to generate the "real" objects that represent 
// the order information passed in from the user's real 
// cart/order interaction. These exist for TESTING ONLY 
// and SHOULD NOT EXIST in the final version of the program
// as all values should be provided by checkout.
const REAL_BENFICIARIES_PER_ITEM_COUNT = 3
const FAKE_BENFICIARIES_PER_ITEM_COUNT = MAX_BENEFICIARIES_PER_ITEM - REAL_BENFICIARIES_PER_ITEM_COUNT;

const REAL_LINE_ITEMS_PER_MERCHANT_COUNT = 4
const FAKE_LINE_ITEMS_PER_MERCHANT_COUNT = MAX_LINE_ITEMS_PER_MERCHANT - REAL_LINE_ITEMS_PER_MERCHANT_COUNT;

const REAL_MERCHANTS_COUNT = 2;
const FAKE_MERCHANTS_COUNT = MAX_TOTAL_MERCHANTS - REAL_MERCHANTS_COUNT;

const PRICE_PER_LINE_ITEM = 20;
const TOTAL_PRICE_PER_MERCHANT = PRICE_PER_LINE_ITEM * REAL_LINE_ITEMS_PER_MERCHANT_COUNT;
const ORDER_TOTAL = TOTAL_PRICE_PER_MERCHANT * REAL_MERCHANTS_COUNT;


(async () => {
  const stdlib = await loadStdlib();
  const startingBalance = stdlib.parseCurrency(10000);

  const createTestAcct = async () => {
    await stdlib.newTestAccount(startingBalance)
  }

  const bakesale = await createTestAcct();
  const ctcBakesale = bakesale.deploy(backend);
  const ctcBakesaleInfo = ctcBakesale.getInfo();

  const buyer = await createTestAcct();
  const ctcBuyer = buyer.attach(backend, ctcBakesaleInfo);

  const createRealBeneficiary = (addr, percentToReceive) => ({
    isReal: true,
    addr,
    parentToReceive
  });

  const createRealLineItem = (totalCost, shipping, tax, beneficiaries) => ({
    isReal: true,
    totalCost,
    shipping,
    tax,
    beneficiaries
  });

  const createRealMerchant = (addr, lineItems) => ({
    isReal: true,
    addr,
    lineItems
  });

  const createOrderData = (orderTotal, Merchants) => ({
    orderTotal, Merchants
  });

  const generateDummyOrderData = async () => {
    const baseBeneficiaries = Promise.all (
      Array.from(REAL_BENFICIARIES_PER_ITEM_COUNT).map(x => {
          const acct = await createTestAcct();
          const addr = acct.networkAccount;
          const pct = 5;
          return createRealBeneficiary(addr, pct)
      })
    ).concat(
      Array.from(FAKE_BENFICIARIES_PER_ITEM_COUNT).map(x => null)
    );

    const baseLineItems = Promise.all (
      Array.from(REAL_LINE_ITEMS_PER_MERCHANT_COUNT).map(x => {
          const totalPrice = stdlib.parseCurrency(PRICE_PER_LINE_ITEM)
          return createRealLineItem(totalPrice, 0, 0, await baseBeneficiaries)
      })
    ).concat(
      Array.from(FAKE_LINE_ITEMS_PER_MERCHANT_COUNT).map(x => null)
    );
    
    const baseMerchants = Promise.all (
      Array.from(REAL_MERCHANTS_COUNT).map(x => {
          const acct = await createTestAcct();
          const addr = acct.networkAccount;
          return createRealMerchant(addr, await baseLineItems);
      })
    ).concat(
      Array.from(FAKE_MERCHANTS_COUNT).map(x => null)
    );

    const orderTotalParsed = stdlib.parseCurrency(ORDER_TOTAL);
    return (async () => createOrderData(orderTotalParsed, await baseMerchants))();
  };

  await Promise.all([
    backend.Bakesale(ctcBakesaleInfo, {}),
    backend.Buyer(ctcBuyer, {
      orderData: async () => {
        return await generateDummyOrderData();
      },
      errorGenericInvalidOrder: () => {
        console.log('Order was not processed due to an error.')
      },
      // alertPaidRecipient: (addr, amt, reason) => {
      //   console.log(`Buyer paid ${amt} to ${addr} for ${reason}.`)
      // }
    }),
  ]);
})();

reachc: The compiler has encountered an internal error: lookup_var v73

Overview

Encountering the following error:

reachc: The compiler has encountered an internal error:

  lookup_var v73

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:73:3 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Util
  impossible, called at src/Reach/Connector/ALGO.hs:388:16 in reach-0.1.2-DAFksisXDyRKXmySyEXCbN:Reach.Connector.ALGO
Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
  Verifying when NO participants are honest
  Verifying when ONLY "HandcraftedFeeAcct" is honest
  Verifying when ONLY "HandcraftedTaxAcct" is honest
  Verifying when ONLY "Merchant" is honest
  Verifying when ONLY "PotentialBuyer" is honest
Checked 156 theorems; No failures!
make: *** [Makefile.index:8: build/index.main.mjs] Error 1

Source

'reach 0.1';


// ========================================================
// Helper Functions
// ========================================================

const emptyOrderMetadata = {
  taxAmt: 0,
  shippingAmt: 0,
  unitPrice: 0, 
  orderID: 0,
  orderTotal: 0
}

const setViewActiveOrderMetadata = (view, orderMetadata) => {
  view.taxAmt.set(orderMetadata.taxAmt);
  view.shippingAmt.set(orderMetadata.shippingAmt);
  view.orderID.set(orderMetadata.orderID);
  view.unitPrice.set(orderMetadata.unitPrice);
  view.orderTotal.set(orderMetadata.orderTotal);
}

const resetViewActiveOrderMetadata = (view) => {
  setViewActiveOrderMetadata(view, emptyOrderMetadata);
}
 
const countTrue = (arr) => arr.reduce(0, (z, x) => z + (x ? 1 : 0))


// ========================================================
// Participants
// ========================================================

// This may need to track more info about contract state.
const OrderMetadataInterface = {
  taxAmt: UInt,
  shippingAmt: UInt,
  orderID: UInt,
  unitPrice: UInt,
  orderTotal: UInt
}

const OrderMetadataTypes = [
  UInt, UInt, UInt, UInt, UInt,
]

const MerchantInterface = {
  getTrialData: Fun([], Object({
    initialTrialDurationInDays: UInt,
    trueUnitPrice: UInt,
  })),
  getArbiterAddresses: Fun([], Object({
    feeAddr: Address,
    taxAddr: Address
  })),
  showOrderCreated: Fun([], Null),
  wantsToApproveOrder: Fun([], Bool),
  wantsToDenyOrder: Fun([], Bool),
  markOrderApprovedAndShipped: Fun([], Null)
}

const potentialBuyerErrors = {
  errorDepositHasAlreadyBeenMade: Fun([], Null),
  errorOrderDenied: Fun([], Null)
}

const potentialBuyerAlerts = {
  alertItemDidNotShip: Fun([], Null),
}

const PotentialBuyerInterface = {
  intendsToPurchase: Fun([], Bool),
  getOrderInfo: Fun([], Object(OrderMetadataInterface)),
  showOrderPaid: Fun(OrderMetadataTypes, Null),
  syncToDb: Fun(OrderMetadataTypes, Null),
  ...potentialBuyerErrors,
  ...potentialBuyerAlerts
}

const ViewInterface = {
  ...OrderMetadataInterface
}


// ========================================================
// Main Contract Logic
// ========================================================

export const main = Reach.App(
  {}, [
    Participant('Merchant', MerchantInterface), 
    ParticipantClass('PotentialBuyer', PotentialBuyerInterface),
    View('ActiveOrderMetadata', ViewInterface),
    Participant('HandcraftedFeeAcct', {}),
    Participant('HandcraftedTaxAcct', {}),
  ], (Merchant, PotentialBuyer, vActiveOrderMetadata, HandcraftedFeeAcct, HandcraftedTaxAcct) => {

    Merchant.only(() => {
      const { initialTrialDurationInDays, trueUnitPrice } = declassify(interact.getTrialData());
      const { feeAddr, taxAddr } = declassify(interact.getArbiterAddresses());
      declassify(interact.showOrderCreated());
    });
    Merchant.publish(initialTrialDurationInDays, trueUnitPrice, feeAddr, taxAddr);

    HandcraftedFeeAcct.set(feeAddr);
    HandcraftedTaxAcct.set(taxAddr);

    assert(balance() == 0);

    /**
     * @var {Bool} hasBeenPurchased
     *   If true, the item has been successfully sold and should
     *   therefore no longer be listed as available for purchase,
     *   either in the contract logic or in the frontend/db.
     * @var {OrderMetadataInterface} finalPaymentAmts
     *   The order metadata to be used for final payouts.
     */
    const [ hasBeenPurchased, finalPaymentAmts ] = 
      parallelReduce([ false, emptyOrderMetadata]) 
        .invariant(balance() == finalPaymentAmts.orderTotal)
        .while(!hasBeenPurchased)
        
        // Steps 2 & 3 - Potential buyer makes a deposit.
        .case(PotentialBuyer,
          (() => ({
            when: declassify(interact.intendsToPurchase())
          })),
          ((_) => {

            // We can assume that a deposit has been made if 
            // the balance is greater than 0. It is not enough 
            // to check for a loop var depositIsActive 
            // because that is set at the end of the step, 
            // but a second user may make end up making a deposit
            // between when the first user makes a deposit and
            // the loop returns the updated depositIsActive.
            if(balance() > 0) {
              PotentialBuyer.only(() =>  declassify(interact.errorDepositHasAlreadyBeenMade()));
              return [
                hasBeenPurchased,
                finalPaymentAmts
              ];
            } else {
              const ThisPotentialBuyer = this;
              assert(balance() == 0);
              commit();

              // Buyer publishes supposed order data from the frontend to be paid
              PotentialBuyer.only(() => {
                // We are having the buyer provide the orderTotal from the front end,
                // so we need to have outside validation of this as well.
                const orderMetadata = declassify(interact.getOrderInfo());
                const { taxAmt, shippingAmt, unitPrice, orderID, orderTotal } = orderMetadata;

                declassify(interact.showOrderPaid(taxAmt, shippingAmt, unitPrice, orderID, orderTotal));
                // This needs to be fleshed out.
                declassify(interact.syncToDb(taxAmt, shippingAmt, unitPrice, orderID, orderTotal));
              });
              PotentialBuyer.publish(orderMetadata)
                .pay(orderMetadata.orderTotal);


              assert(balance() == orderMetadata.orderTotal);
              setViewActiveOrderMetadata(vActiveOrderMetadata, orderMetadata);


              // 4. Approval/refund logic
              const [ orderTimedOut, orderDenied, orderApproved ] = 
                parallelReduce([ false, false, false ])
                  .invariant((countTrue(array(Bool, [orderTimedOut, orderDenied, orderApproved])) <= 1)    
                    && (balance() == orderMetadata.orderTotal))
                  .while(!orderTimedOut && !orderDenied && !orderApproved)
                  .case(
                    Merchant,
                    (() => ({ when: declassify(interact.wantsToApproveOrder())})),
                    () => { return [ false, false, true ]; }
                  )                  
                  // Commented out until fix is released: https://github.com/reach-sh/reach-lang/issues/205#issuecomment-873118085
                  // .case(
                  //   Merchant,
                  //   (() => ({ when: declassify(interact.wantsToDenyOrder())})),
                  //   () => { return [ false, true, false ]; }
                  // )
                  //
                  // Test case, not true timeout.
                  .timeout(1000, () => {
                    Anybody.publish();
                    return [ false, false, true ];
                  });  

              // Verification fails without this. Seems like it's needed
              // to protect against some sort of malicious activity in 
              // the timeout due to Anybody.publish().
              if(balance() != orderMetadata.orderTotal) {
                transfer(balance()).to(ThisPotentialBuyer);
                return [ false, emptyOrderMetadata];
              } else {
                return [ true, orderMetadata ];
              }
            }
          })
        ) 
        .timeout(false);

    commit();
    Anybody.publish();
    transfer(finalPaymentAmts.orderTotal).to(Merchant);
    commit();
    exit();
  }
);

Using `address` as a key in `Object` throws compiler errors

const UserEntryType = Object({
    address: Address,
    returnedValue: UInt,
    timestamp: UInt
});

gives:

reachc: The compiler has encountered an internal error:

  solc failed:
STDOUT:

STDERR:
Error: Expected identifier but got 'address'
  --> /tmp/reachc-sol-59cc096600b49f45/compiled.sol:91:19:
   |
91 |   address payable address;
   |                   ^^^^^^^

whereas changing the key to anything else like:

const UserEntryType = Object({
    add: Address,
    returnedValue: UInt,
    timestamp: UInt
});

works fine

parallelReduce subsequent visit issues

The parallelReduce loop works correctly for the first visit of ParticipantClass Giver who pays, sets when=false, and calls interact.stopWatching which calls process.exit(0). For subsequent visits, the parallelReduce loop seems to ignore declassify, and, instead, uses the declassified data from the first visit. Here is index.rsh. Glad to provide more data or a demo.

'reach 0.1';

const CommonAPI = {
  reportProjectName: Fun([Bytes(64)], Null),
  reportContractBalance: Fun([UInt], Null),
  reportTimeout: Fun([], Null),
  stopWatching: Fun([], Null)
}

const ReceiverAPI = {
  ...CommonAPI,
  projectName: Bytes(64),
  projectGoal: UInt,
  projectDuration: UInt
};

const GiverAPI = {
  ...CommonAPI,
  getGift: Fun([], UInt),
  askToGive: Fun([], Bool),
  reportPayment: Fun([UInt], Null),
  reportDone: Fun([], Null)
};

export const main = Reach.App(() => {
  const R = Participant('Receiver', ReceiverAPI);
  const G = ParticipantClass('Giver', GiverAPI);
  deploy();

  R.only(() => {
    const p = {
      name: declassify(interact.projectName),
      goal: declassify(interact.projectGoal),
      duration: declassify(interact.projectDuration)
    }
  });

  R.publish(p);
  R.interact.stopWatching();

  const [inLoop, sum] = parallelReduce([true, 0])
    .invariant(balance() == sum)
    .while(inLoop && balance() < p.goal)
    .case(
      G,
      (() => {
        const shouldGive = declassify(interact.askToGive());
        if (!shouldGive) { interact.stopWatching(); }
        return { when: shouldGive, msg: declassify(interact.getGift()) }
      }),
      ((gift) => gift),
      ((gift) => {
        G.only(() => {
          interact.reportPayment(gift);
          interact.reportContractBalance(balance());
        });
        return [true, balance()];
      })
    )
    .timeout(p.duration, () => {
      G.interact.reportTimeout();
      Anybody.publish();
      return [false, sum];
    });

  transfer(balance()).to(R);
  commit();
  G.interact.reportDone();

  exit();
});

Supporting documentation for workshops: defining what "data types" are available

Summary

  • In our workshops, we ask the client to plan their script. We prompt them specifically to think of the "data types" that they will need. For a non-Javascript engineer, they might not know what's possible. We could link to the types available.

Section and Link

Issue

  • They might not know what data types are available. Providing a link to data types to match the logic could be very useful (it would have been for me).

Recommendation

  • We should explain the available data types in a link when prompted to think of pseudo logic.

Supporting Links

Encountering race condition in tutorial 9 - Web Interaction

In tutorial 9, the contract information is rendered after deploying the contract as Alice. Before I attach to the contract as Bob, the following unhandled exception shows up:

frontend-error

Steps to reproduce:

  1. Follow the tutorial from start to end.

To open the react application:

2. ./reach react 
  1. In the frontend, click on Deployer -> Set Wager -> Deploy -> Choose Ropsten Network in Metamask -> Submit. At this point, I got the unhandled exception.

This happens when using the Ropsten test network, but works fine when using Ganache.

Compiler internal error

The following code

'reach 0.1';
'use strict';

const TIMEOUT_PERIOD = 60 * 1000;
//const MINIMUM_FEE = 1000;

//-----------------------------------------------------------------------------
// Token operative & compliance parameters
//-----------------------------------------------------------------------------

const TokenParameters = Object({
  maxTransfers: UInt,
})

//-----------------------------------------------------------------------------
// Interaction interfaces
//-----------------------------------------------------------------------------

const IManager = {
  getBootstrapParams: Fun([], Tuple(Token, TokenParameters)),
  setupComplete: Fun([], Null)
}

const ISender = {
  getAxfer: Fun([], Tuple(UInt))
}

const IReceiver = {
  accAxfer: Fun([UInt], Bool)
}

//-----------------------------------------------------------------------------
// Helper functions
//-----------------------------------------------------------------------------
function validateParams(params) {
  assume(params.maxTransfers >= 1);
}

//-----------------------------------------------------------------------------
// DApp Entry point
//-----------------------------------------------------------------------------
export const main = Reach.App(
  {}, [
    Participant('Manager', IManager),
    ParticipantClass('Sender', ISender),
    ParticipantClass('Receiver', IReceiver)],
  (Manager, Sender, Receiver) => {

    // Step1:Manager must set token parameters

    Manager.only(() => {
      const [token, params] = declassify(interact.getBootstrapParams());
      validateParams(params);
      interact.setupComplete();
    })
    Manager.publish(token, params);

    var run = true
    invariant (balance() == 0 && balance(token) == 0)
    while(run) {
      Sender.only(() => {
        
      })

      Receiver.only(() => {

      })

      commit()
      Anybody.publish()
      
      continue;
    }

    commit();
  }
);

will cause an internal compiler error as follows:

Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
  Verifying when NO participants are honest
  Verifying when ONLY "Manager" is honest
  Verifying when ONLY "Receiver" is honest
  Verifying when ONLY "Sender" is honest
Checked 34 theorems; No failures!
reachc: The compiler has encountered an internal error:

  3 lookup_let v29 not in v33, v49, v51, v56, v351, v352

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:66:3 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Util
  impossible, called at src/Reach/Connector/ALGO.hs:336:7 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Connector.ALGO

Thanks.

returns inside if statements doesn't return the value

This was something jbo in the Discord server encountered
while defining functions in .rsh code, having return statements inside if block doesn't work as expected

Here is the contract I wrote the reproduce the error

// BACKEND (.rsh)

'reach 0.1';

export const main = Reach.App(() => {
    const Alice = Participant('Alice', {
        log: Fun(true, Null)
    });
    deploy();

    Anybody.publish();

    const state = {
        roll: 12
    };

    const cmd = {
        skip: true
    };

    const p1 = 1;

    function attempt(localGameState, player, buildCmd) {
        if (buildCmd.skip) {
            return {
                winner: 2,
                roll: localGameState.roll,
                turn: player
            };
        }

        return {
            winner: buildCmd.skip ? 1 : 0,
            roll: 0,
            turn: 0
        };
    }

    const result = attempt(state, p1, cmd)

    Alice.interact.log(result);


    commit();
    exit();
});

// FRONTEND (.mjs)

import { loadStdlib } from '@reach-sh/stdlib';
import * as backend from './build/index.main.mjs';

(async () => {
    const stdlib = await loadStdlib();
    const startingBalance = stdlib.parseCurrency(100);

    const alice = await stdlib.newTestAccount(startingBalance);

    const ctcAlice = alice.deploy(backend);


    await backend.Alice(ctcAlice, {
        log: (x) => {
            console.log("{");
            for (let obj of Object.keys(x)) {
                console.log(`\t${obj}: ${stdlib.bigNumberToNumber(x[obj])}`);
            }
            console.log("}");
        }
    });
})();

// Expected result
/*
{
    roll: 12
    turn: 1
    winner: 2
}
*/

// Actual result
/*
{
    roll: 0
    turn: 0
    winner: 1
}
*/

Error running multisig example through make run-all

The following report includes the exact steps I took to reach an error as well as the error log I received. Unfortunately I wasn't able to recreate the error, so the steps are a bit convoluted.

Initially the multisig example failed when running make run-all with the attached error. Running make run-all a second time led to the same error. After this failed, I tried running make run inside the multisig folder which succeeded. I then tried running make run-all again which also succeeded. After deleting and re-cloning the repository, the multisig example still worked properly. My best guess is that there's something locally cached from the multisig build, but I can't recreate the initial issue.

Successfully tagged reachsh/examples-multisig:v0.1.1
WARNING: Image for service reach-app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
{"jsonrpc":"2.0","id":67,"result":"Geth/v1.9.2-stable-e76047e9/linux-amd64/go1.12.7"}

> @reach-sh/[email protected] pretest /app
> eslint --ignore-path .gitignore --ext .mjs .


> @reach-sh/[email protected] test /app
> node --experimental-modules index.mjs

(node:31) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module /app/build/multisig.mjs imported from /app/index.mjs
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:73:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:149:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
    at link (internal/modules/esm/module_job.js:42:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @reach-sh/[email protected] test: `node --experimental-modules index.mjs`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @reach-sh/[email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2020-03-18T20_31_50_712Z-debug.log
make[1]: *** [run] Error 1
make: *** [run-all] Error 2

Timeout in Rock Paper Scissors example

When running make run-all after downloading the repository, the RPS test appears to have hung. No new output occurred for around a minute and so I terminated the process and reran the make run-all script. The second time, RPS ran correctly without any delay around this step.

Below is the segment of the log that occurred before the hang.

Running game that times out

Alice initiates a new game.
Alice publishes parameters of game: wager of 1.5ETH and escrow of 0.15ETH.
Bob accepts the terms: wager of 1500000000000000000WEI and escrow of 150000000000000000WEI.
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
(local: Alice plays SCISSORS.)
Alice commits to play with (hidden) hand.

Below is the output from that same segment in the second run which succeeded.

Alice initiates a new game.
Alice publishes parameters of game: wager of 1.5ETH and escrow of 0.15ETH.
Bob accepts the terms: wager of 1500000000000000000WEI and escrow of 150000000000000000WEI.
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
Alice takes her sweet time...
(local: Alice plays PAPER.)
Alice commits to play with (hidden) hand.
Alice thinks outcome is Alice quits.
Bob thinks outcome is Alice quits.
Observer thinks outcome is Alice quits.
Done!

Reach 0.1 does not work

$ ./reach compile
Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 11, in <module>
    load_entry_point('docker-compose==1.25.0', 'console_scripts', 'docker-compose')()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 72, in main
    command()
  File "/usr/lib/python3/dist-packages/compose/cli/main.py", line 125, in perform_command
    project = project_from_options('.', options)
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 53, in project_from_options
    return get_project(
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 156, in get_project
    execution_context_labels(config_details, environment_file),
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 163, in execution_context_labels
    '{0}={1}'.format(LABEL_CONFIG_FILES, config_files_label(config_details)),
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 172, in config_files_label
    return ",".join(
  File "/usr/lib/python3/dist-packages/compose/cli/command.py", line 173, in <genexpr>
    map(str, (os.path.normpath(c.filename) for c in config_details.config_files)))
  File "/usr/lib/python3.8/posixpath.py", line 336, in normpath
    path = os.fspath(path)
TypeError: expected str, bytes or os.PathLike object, not NoneType

It's reach from later master branch.

Reach Compiler Error - Maybe Red Herring?

Summary

Received the following error after running reach compile. Error prevents the file from being actually compiled, but may be a red-herring.

$:: REACH_CONNECTOR_MODE=ALGO reach compile index.rsh
reachc: The compiler has encountered an internal error:

  6 lookup_let v109 not in v28, v30, v34, v35, v37, v76, v77, v79, v92, v93, v95, v96, v97, v98, v99, v100, v101, v105, v126, v679, v680

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:66:3 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Util
  impossible, called at src/Reach/Connector/ALGO.hs:366:7 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Connector.ALGO
Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
  Verifying when NO participants are honest
  Verifying when ONLY "Arbitrator" is honest
  Verifying when ONLY "Contractor" is honest
  Verifying when ONLY "Primary" is honest
Checked 123 theorems; No failures!

Steps To Replicate(?)

I commented the hell out of the code until it both reliably compiled and threw the error. Culprit was this conditional:

// Payouts: pay contractor if verified; else pay seller
  const arbitratorFee = balance() / 50;
  const bulk = balance() - arbitratorFee;

  // Error caused by conditional statement below

  Anybody.publish();
  if (review == STATUS.VERIFIED) {
    transfer(bulk).to(Contractor);
    commit();
  } else {
    transfer(bulk).to(Primary);
    commit();
  }

Background

  • The index.rsh file contains only one line (a closeTo) below the errant conditional.
  • This conditional splits a primary user's payment between two others.
  • The error persists in all the following scenarios:
    • Replacing Anybody with race( ... )
    • Defining the arbitratorFee const inside the conditional scope
    • Moving the publish statement into the conditional scope
    • Specifying a Participant to do the publishing
  • STATUS.VERIFIED is a reference to the following, also defined in index.rsh (above the App export):
const STATUS = {
  OPEN: 1,
  INPROGRESS: 2,
  REVIEW: 3,
  VERIFIED: 4,
  CANCELED: 5,
};

Additional notes

  • I think Reach had an issue with how I was attempting to handle the transfer logic there
  • Temporarily circumvented with a fork statement

Environment

  • MacOS 11.X
  • nodeJS v15.3.0
  • Docker 20.10.6
  • @reach-sh/stdlib ^0.1.2-rc.56

Hope this helps: I will keep a revision of the error-generating code around, just in case. Otherwise, please close or redirect this issue as needed. Cheers!

Doc: 5.4.6.1.7 parallelReduce explanation and parameters definations

Page Link

https://docs.reach.sh/ref-programs-consensus.html#%28reach._%28%28parallel.Reduce%29%29%29

Search String

5.4.6.1.7 parallelReduce section

Issue

  1. Looking for a High-level explanation and some definition of the parameters for

'ParalleReduce([ true, Funder, 0 ])'

  1. Click on .Case brings you to https://docs.reach.sh/ref-programs-compute.html#%28reach._%28%28case%29%29%29
    which does not look relevant in this use case

Suggestion

  1. High-level explanation and some definition or examples setting parameters for

'ParalleReduce([ true, Funder, 0 ])'
2) Some explaination of how function .Case() works and expecting which parameters as inputs

Uncaught Error: hexAddress should be passed as a Buffer

I understand this has been reported, and am creating an issue to help track it as suggested.

Issue

Although the .rsh file compiles with no failures, the following error is encountered when running the app in the browser:

Uncaught Error: hexAddress should be passed as a Buffer

Screen Shot 2021-06-26 at 6 10 04 PM

Context

Encountered while building a Reach application inspired by the NFT Dumb example. Tested as far back as rc-46 of stdlib.
File contents below.

"reach 0.1";

const AuctionProps = Object({
  assetId: UInt,
  description: Bytes(128),
  price: UInt,
});

const BuyerProps = {
  getBid: Fun([UInt], UInt),
  getNewOwner: Fun([], Address),
  showSaleItem: Fun([], Null),
};

const OwnerInterface = {
  getSaleProps: Fun([], AuctionProps),
  ...BuyerProps,
};

export const main = Reach.App(() => {
  const Owner = Participant("Owner", OwnerInterface);
  const Buyer = ParticipantClass("Buyer", BuyerProps);
  const vNFTSale = View("vNFTSale", {
    assetId: UInt,
    description: Bytes(128),
    owner: Address,
    price: UInt,
  });
  deploy();

  Owner.only(() => {
    const props = declassify(interact.getSaleProps());
  });
  Owner.publish(props);

  vNFTSale.assetId.set(props.assetId);
  vNFTSale.description.set(props.description);
  vNFTSale.owner.set(Owner);
  vNFTSale.price.set(props.price);

  var owner = Owner;
  invariant(balance() == 0);
  while (owner == Owner) {
    commit();

    Buyer.only(() => {
      // Show what's on sale (allows the front-end to use vNFTSale)
      interact.showSaleItem();

      const amOwner = this == owner;
      // Allow Owner to specify a receiver address directly, and pay nothing
      const price = amOwner ? 0 : declassify(interact.getBid(props.price));
      const newOwner = amOwner ? declassify(interact.getNewOwner()) : this;
    });

    Buyer.publish(price, newOwner).pay(price);
    transfer(balance()).to(Owner);

    owner = newOwner;
    continue;
  }

  commit();
  exit();
});

Compiler internal error, ETH Connector

Using Reach with the following code:

'reach 0.1'
'use strict'

const IAdministrator = {
    getNewEntry: Fun([],Address),
}

const IRegistryView = {
    last: UInt
}

export const main = Reach.App({
    deployMode: "constructor" 
    },
    [ Participant('Administrator', IAdministrator),
      View('RegistryView', IRegistryView) ], 
     (Admin, RegistryView) => {
        Admin.publish();
        
        const registry = new Set()

        const isRunning = parallelReduce(true)
            .invariant(balance () == 0)  // No funds movement, should validate always
            .while(isRunning)
            .case(
                Admin,
                /* publish_expr */
                (() => ({
                    msg: declassify(interact.getNewEntry())
                })),
                /* pay_expr */
                ((_) => 0),
                /* consensus_expr */
                ((addr) => {
                    registry.insert(addr);
                    return isRunning;
                })
            )

        commit();
    })

yields:

hernandp@LAPTOP-QJTRSF6V:~/src/reach-scratchpad/03-registry$ ./reach compile registry.rsh
Verifying knowledge assertions
Verifying for generic connector
  Verifying when ALL participants are honest
  Verifying when NO participants are honest
  Verifying when ONLY "Administrator" is honest
Checked 12 theorems; No failures!
reachc: The compiler has encountered an internal error:

  sol view defn

This error indicates a problem with the Reach compiler, not your program. Please report this error, along with the pertinent program, to the Reach team as soon as possible so we can fix it.

Open an issue at: https://github.com/reach-sh/reach-lang/issues

CallStack (from HasCallStack):
  error, called at src/Reach/Util.hs:67:3 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Util
  impossible, called at src/Reach/Connector/ETH_Solidity.hs:1223:36 in reach-0.1.2-1JzW2Z5sBxAzanGaqepiq:Reach.Connector.ETH_Solidity

Platform information:

Linux LAPTOP-QJTRSF6V 5.4.72-microsoft-standard-WSL2 #1 SMP Wed Oct 28 23:40:43 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

reach version output:

reach 0.1

Thanks.

Both branches of ternary opeator is evaluated while using loops

https://gist.github.com/Zetsuboii/05e473ac22d1ebd176ed8b0b126ecc7a
This is what I've written to produce the error.

https://gist.github.com/Zetsuboii/3e5792bdfeb3970e5a4eeae4ea856404
This is a similar code without the loop

Without the loop, compiler only evaluates the possible branches.
But when loop is involved const temp = i < 5 ? arr[i] : i; this line, which normally would work fine because arr has the length of 5, gives array out of bounds error.

using `postWager` in interact interface gives compilation error

const FunderInterface =
{
    ...CommonInterface,
    getBounty: Fun([], Object({
        deadline: UInt,
        amt: UInt,
    })),
    postWager: Fun([], Null)
}

gives

file:///app/build/index.main.mjs:382
  stdlib.protect(ctc2, await interact.postWager(), {
                                      ^

TypeError: interact.postWager is not a function
    at Module.Funder (file:///app/build/index.main.mjs:382:39)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Promise.all (index 0)
    at async file:///app/index.mjs:122:5
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @reach-sh/stonk-wars-index@ index: `node --experimental-modules --unhandled-rejections=strict index.mjs`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @reach-sh/stonk-wars-index@ index script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-06-11T02_59_57_847Z-debug.log
ERROR: 1
Makefile.index:20: recipe for target 'run-target' failed
make[1]: *** [run-target] Error 1
make[1]: Leaving directory '/mnt/d/my-projs/stonk-wars'
Makefile.index:16: recipe for target 'run' failed
make: *** [run] Error 2

Definition of 'assertions' in this paragraph gets jumbled

Description
This section is supposed to explain that these are all assertions but I don't think it's clear. I think it refers to some as assertions and some not, when they all are.

Page Link
https://docs.reach.sh/ref-model.html

Search String
"An assertion is either: a knowledge assertion, which is a claim that one honest participant..."

Issue
I talked to Jay about this and it turns out they are all assertions. Here is what was discussed:
Me: Are 'assumption' and 'requirement' also types of assertions? This wording is confusing.
Jay: Yes. There are assertions of five flavors: static, assumption, requirement, possibility, knowledge. The functions that get you them in the code are assert, assume, require, possible, unknowable

Suggestion
Just clarifying that these are all, in fact, assumptions, helped me group the info and make a better note of it.

Error when using Relay 26be,26be,send,m1,false,SEND REPEAT @ 601 x 33 / Also Related to Algorand

I'm receiving this error in projects that implement a Relay account. Here's the debug information for an interactive test runner. Using the Relay example

Starting example game as Relay
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
n
Please paste the contract information:
{"address":"0xC87539117dfE46FEa8366eFaef3c37C1520e4BeF","creation_block":597,"transactionHash":"0xe7972ce74878e5af997396e9fa908a494d067ce14481cbfc124d8a24cbb52e61"}
Relay balance is: 1000
Alice creates a Relay account.
Alice shares it with Bob outside of the network. {"_isSigner":true,"address":"0x26beBf4a1a4688d8764b85D429e70BAD5171c432","provider":{"_isProvider":true,"_events":[],"_emitted":{"block":-2,"t:0x34c10f3768c7e43d32657f40e79151d324fdc22e03f7be32d7a26d6eda315b32":600,"t:0xd6b518f69dcbd3500dc1efa48b8f6780e2dedc91caf50f2d1c320ca96c72d661":601},"formatter":{"formats":{"transaction":{},"transactionRequest":{},"receiptLog":{},"receipt":{},"block":{},"blockWithTransactions":{},"filter":{},"filterLog":{}}},"anyNetwork":false,"_networkPromise":{},"_maxInternalBlockNumber":601,"_lastBlockNumber":-2,"_pollingInterval":500,"_fastQueryDate":1625760988942,"connection":{"url":"http://ethereum-devnet:8545"},"_nextId":74,"_eventLoopCache":{"detectNetwork":null,"eth_chainId":null,"eth_blockNumber":null},"_network":{"chainId":1337,"name":"unknown"},"_internalBlockNumber":{},"_fastBlockNumber":601,"_fastBlockNumberPromise":{}}}
impossible: The message you are trying to send appears to be invalid.
Error: execution reverted
at getResult (/stdlib/node_modules/@ethersproject/providers/lib/json-rpc-provider.js:128:21)
at processJsonFunc (/stdlib/node_modules/@ethersproject/web/lib/index.js:309:22)
at /stdlib/node_modules/@ethersproject/web/lib/index.js:241:46
at step (/stdlib/node_modules/@ethersproject/web/lib/index.js:33:23)
at Object.next (/stdlib/node_modules/@ethersproject/web/lib/index.js:14:53)
at fulfilled (/stdlib/node_modules/@ethersproject/web/lib/index.js:5:58)
at runMicrotasks ()
at processTicksAndRejections (internal/process/task_queues.js:95:5) {
code: 3,
data: '0x100960cb0000000000000000000000000000000000000000000000000000000000000008'
}
args:
[
[ BigNumber { _hex: '0x0255', _isBigNumber: true } ],
[
BigNumber { _hex: '0x015af1d78b58c40000', _isBigNumber: true },
'0x26beBf4a1a4688d8764b85D429e70BAD5171c432'
]
]
/stdlib/dist/cjs/ETH_like.js:786
throw Error(dhead + " REPEAT @ " + block_send_attempt + " x " + block_repeat_count);
^

Error: 26be,26be,send,m1,false,SEND REPEAT @ 601 x 33
at Object. (/stdlib/dist/cjs/ETH_like.js:786:51)
at step (/stdlib/dist/cjs/ETH_like.js:44:23)
at Object.next (/stdlib/dist/cjs/ETH_like.js:25:53)
at fulfilled (/stdlib/dist/cjs/ETH_like.js:16:58)
at runMicrotasks ()

====
This also appears on Algorand here is the test runner debug information.

Please paste the contract information:
{"ApplicationID":2,"creationRound":13,"Deployer":"6J3K2FVIHK2IEXRIJ52JMZHM3J5XDY7NGZUIZP3FXXSG276OGNKFX3JVXI"}
Relay balance is: 1000
Alice creates a Relay account.
Alice shares it with Bob outside of the network. {"addr":"HYBRXGYCFV56TVVFMSDDMVVB36FZB72GVXLCHZ4SDTPPYTIUJOYGKLPZNE","sk":{"0":107,"1":230,"2":121,"3":162,"4":155,"5":30,"6":171,"7":186,"8":175,"9":205,"10":189,"11":57,"12":130,"13":222,"14":139,"15":136,"16":40,"17":97,"18":63,"19":190,"20":164,"21":215,"22":180,"23":213,"24":62,"25":49,"26":28,"27":203,"28":185,"29":40,"30":217,"31":216,"32":62,"33":3,"34":27,"35":155,"36":2,"37":45,"38":123,"39":233,"40":214,"41":165,"42":100,"43":134,"44":54,"45":86,"46":161,"47":223,"48":139,"49":144,"50":255,"51":70,"52":173,"53":214,"54":35,"55":231,"56":146,"57":28,"58":222,"59":252,"60":77,"61":20,"62":75,"63":176}}
/stdlib/dist/cjs/ALGO.js:1461
throw Error(dhead + " --- ABORT");
^

Error: BRXG: BRXG sendrecv m1 false --- ABORT
at /stdlib/dist/cjs/ALGO.js:1461:67
at step (/stdlib/dist/cjs/ALGO.js:66:23)
at Object.throw (/stdlib/dist/cjs/ALGO.js:47:53)
at step (/stdlib/dist/cjs/ALGO.js:51:139)
at Object.throw (/stdlib/dist/cjs/ALGO.js:47:53)
at rejected (/stdlib/dist/cjs/ALGO.js:39:65)
at processTicksAndRejections (internal/process/task_queues.js:95:5)

.rsh checking for empty string with == gives wrong answer

// index.rsh
'reach 0.1';

export const main = Reach.App(() => {
  const Alice = Participant('Alice', {goop: Fun([], Bytes(10))});
  const Bob   = Participant('Bob', {bloop: Fun([Bool], Null)});
  deploy();
  // write your program here
  Alice.only(() => {
    const s = declassify(interact.goop());
  });
  Alice.publish(s);
  commit();
  Bob.interact.bloop(s == '');
});
// index.mjs
import {loadStdlib} from '@reach-sh/stdlib';
import * as backend from './build/index.main.mjs';

(async () => {
  const stdlib = await loadStdlib(process.env);
  const startingBalance = stdlib.parseCurrency(100);

  const alice = await stdlib.newTestAccount(startingBalance);
  const bob = await stdlib.newTestAccount(startingBalance);

  const ctcAlice = alice.deploy(backend);
  const ctcBob = bob.attach(backend, ctcAlice.getInfo());

  console.log(`expected:`);
  console.log(true);
  console.log(`actual:`);
  await Promise.all([
    backend.Alice(ctcAlice, { goop: () => '' }),
    backend.Bob(ctcBob, { bloop: (b) => console.log(b) }),
  ]);

  console.log('Done');
})();

Output of reach run:

expected:
true
actual:
false

No Docker Images for Tutorial

Hey there! Enjoying learning Reach so far, the tutorial is really well done.

Just going through the tutorial and arrived at this section: https://docs.reach.sh/tut-8.html and running make run-alice returns the following error, even after docker login.

[austin:~/projects/reach-hello-wrold] main(+4/-0)* 4s ± make run-alice
docker-compose run --rm alice
Starting reach-hello-wrold_ethereum-devnet_1 ... done
Pulling alice (reachsh/reach-app-tut-8:latest)...
ERROR: pull access denied for reachsh/reach-app-tut-8, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
Makefile:35: recipe for target 'run-alice' failed
make: *** [run-alice] Error 1

The docker-compose.yml is copied directly from the tutorial. Checking out reachsh on dockerhub and it looks like the docker image indeed does not exist.

Let me know if I can provide any more info, or if I missed a step in the tutorial.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.