Decentraland Coding Challenge

Decentraland is an open-source virtual world owned by its users. Users can create their own experiences and share them with others through an open system.

The Decentraland community is looking for top-tier developers to tackle the implementation of a new World Explorer in Bevy, opening the gates of the platform to more open-source developers from around the globe.

This new world explorer will be built from the ground up, inspired by the current implementation, and aims to become the reference implementation of Decentraland as it matures in the long term. As an idealistic and forward-looking implementation, based on technologies that hold great promise for the future, this project prioritizes solid fundamentals, extensibility, and the use of modern open-source frameworks like Bevy. In order to select the lead developer for this project, we ask of you to complete this challenge.

The Challenge

This is the first of two challenges you will be presented to be considered as a candidate for the position of lead developer of the Bevy-based client.

While moving through the world of Decentraland, users enter and leave scenes which control objects and their behavior in a certain area. The script of each scene is executed by the World Explorer in a sandboxed environment to ensure the security and stability of the experience.

In this first stage, you will create a proof-of-concept runtime environment similar in nature to the one that runs Decentraland scenes.

You must push your solution to a GitHub repository before midnight on February 5th, and send an email to challenge@decentraland.org including the URL. Note that you must have previously been selected to qualify for the monetary reward of completing this challenge.

Goal

Write a program that embeds a JavaScript runtime to execute a script in a sandboxed environment, providing access to functionality outside the sandbox. The code you will run, and the objects you will provide, are a simplified version of a minimal Decentraland scene runtime.

Requirements

Ensure that your program is in line with these requirements:

  • Language: it must be written in Rust.
  • Compliance: it must produce the exact specified output (see below).
  • Code quality: the code must be readable, well-organized and well-architectured.
  • Running script: it must run with a specific script (see below).
  • License: it must include an Apache License 2.0 file, as the Decentraland source.
  • Functionality:
    1. Create a JavaScript sandbox that provides a number of global objects (see below).
    2. Load the test file in the sandboxed environment (see below).
    3. Call and await the module.exports.onStart() method (simulating initialization).
    4. Call and await the module.exports.onUpdate(deltaTime) method three times, with the deltaTime sequence 1, 2, 3 (simulating 1 tick per second).
    5. Handle messages sent from inside the sandbox during the simulation.

Global Objects

The sandboxed environment must make the following globals available to the scene. In pseudocode resembling TypeScript:

type EngineModule = {
  async sendMessage(message: string): void // send data outside the environment, in order to log it
}

type Console = {
  log(text: string): void // *immediately* write text to stdout
}

declare const console: Console

declare function require(moduleName: "~engine"): EngineModule
declare function require(moduleName: string): any // throw an error

In more detail, the require implementation provided to the sandboxed script must be compatible with this example JavaScript one (but running outside the sandbox in the language of choice):

function require(moduleName) {
  if (moduleName !== '~engine') {
    throw new Error('Unknown module')
  }

  return {
    async sendMessage(message) {
      console.log("EngineModule: sendMessage: " + message)
    }
  }
}

Sandboxed Code

Inside the sandboxed environment, the following code must run:

const engine = require("~engine")

module.exports.onStart = async function() {
  console.log("Scene: onStart")
}

module.exports.onUpdate = async function(dt) {
  console.log("Scene: onUpdate: begin: " + dt)
  
  console.log("Scene: onUpdate: sendMessage: " + dt)
  await engine.sendMessage("" + dt)

  console.log("Scene: onUpdate: end: " + dt)
}

Expected Execution and Output

Your program must run as follows, from the root of your project:

$ ./bin/run

Ensure that the run script takes care of any preparations your submission needs.

The project will run in a Unix shell environment with cargo installed.

During the course of the execution, your program must write the following verbatim output (and nothing else) to stdout:

Scene: onStart
Scene: onUpdate: begin: 1
Scene: onUpdate: sendMessage: 1
EngineModule: sendMessage: 1
Scene: onUpdate: end: 1
Scene: onUpdate: begin: 2
Scene: onUpdate: sendMessage: 2
EngineModule: sendMessage: 2
Scene: onUpdate: end: 2
Scene: onUpdate: begin: 3
Scene: onUpdate: sendMessage: 3
EngineModule: sendMessage: 3
Scene: onUpdate: end: 3

Ready?

We hope to hear from you and see what you build!

Reach out to us at challenge@decentraland.org if you have any questions.

Good luck!