Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hello World example #12

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,3 @@ FROM mcr.microsoft.com/devcontainers/base

COPY --from=avalanchego /avalanchego/build /go/src/github.com/ava-labs/avalanchego/build
COPY --from=avalanche-cli /avalanche /usr/local/bin/avalanche

COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge
COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast
COPY --from=foundry /usr/local/bin/anvil /usr/local/bin/anvil
COPY --from=foundry /usr/local/bin/chisel /usr/local/bin/chisel
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ To get a comprehensive introduction to Precompile-EVM, take the Avalanche Academ

## How to use

There is an example branch [hello-world-example](https://github.com/ava-labs/precompile-evm/tree/hello-world-example) in this repository. You can check the example branch to see how to register precompiles and test them.

### 1. Generate Precompile Files

First, you need to create your precompile contract interface in the `contracts` directory and build the ABI. Then you can generate your precompile as such:
Expand All @@ -61,6 +59,8 @@ First, create the configuration for your subnet.
avalanche blockchain create myblockchain --custom --vm $AVALANCHEGO_PLUGIN_PATH/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy --genesis ./.devcontainer/genesis-example.json
```

Confirm that the new `holamundo/` directory has the appropriate files.

Next, launch the Subnet with your custom VM:

```bash
Expand All @@ -85,4 +85,5 @@ In order to upgrade the Subnet-EVM version, you need to change the version in `g
[v0.2.4] [email protected] (Protocol Version: 37)
[v0.2.5] [email protected] (Protocol Version: 38)
[v0.3.0] [email protected] (Protocol Version: 39)
[v0.4.0] [email protected]/1.13.0-fuji/1.13.0 (Protocol Version: 39)
```
1 change: 1 addition & 0 deletions compatibility.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"rpcChainVMProtocolVersion": {
"v0.4.0": 39,
"v0.3.0": 39,
"v0.2.5": 38,
"v0.2.4": 37,
Expand Down
9 changes: 0 additions & 9 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,6 @@ Subnet-EVM must activate any precompiles used in the test in the genesis:
{
"config": {
"chainId": 43214,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"feeConfig": {
"gasLimit": 8000000,
"minBaseFee": 25000000000,
Expand Down
Empty file removed contracts/contracts/.gitkeep
Empty file.
19 changes: 19 additions & 0 deletions contracts/contracts/ExampleHelloWorld.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./interfaces/IHelloWorld.sol";

address constant HELLO_WORLD_ADDRESS = 0x0300000000000000000000000000000000000000;

// ExampleHelloWorld shows how the HelloWorld precompile can be used in a smart contract.
contract ExampleHelloWorld {
IHelloWorld helloWorld = IHelloWorld(HELLO_WORLD_ADDRESS);

function sayHello() public view returns (string memory) {
return helloWorld.sayHello();
}

function setGreeting(string calldata greeting) public {
helloWorld.setGreeting(greeting);
}
}
Empty file.
13 changes: 13 additions & 0 deletions contracts/contracts/interfaces/IHelloWorld.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;
import "@avalabs/subnet-evm-contracts/contracts/interfaces/IAllowList.sol";

interface IHelloWorld is IAllowList {
event GreetingChanged(address indexed sender, string oldGreeting, string newGreeting);
// sayHello returns the stored greeting string
function sayHello() external view returns (string calldata result);

// setGreeting stores the greeting string
function setGreeting(string calldata response) external;
}
Empty file removed contracts/contracts/test/.gitkeep
Empty file.
42 changes: 42 additions & 0 deletions contracts/contracts/test/ExampleHelloWorldTest.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../ExampleHelloWorld.sol";
import "../interfaces/IHelloWorld.sol";
import "@avalabs/subnet-evm-contracts/contracts/test/AllowListTest.sol";

contract ExampleHelloWorldTest is AllowListTest {
IHelloWorld helloWorld = IHelloWorld(HELLO_WORLD_ADDRESS);

function step_getDefaultHelloWorld() public {
ExampleHelloWorld example = new ExampleHelloWorld();
address exampleAddress = address(example);

assertRole(helloWorld.readAllowList(exampleAddress), AllowList.Role.None);
assertEq(example.sayHello(), "Hello World!");
}

function step_doesNotSetGreetingBeforeEnabled() public {
ExampleHelloWorld example = new ExampleHelloWorld();
address exampleAddress = address(example);

assertRole(helloWorld.readAllowList(exampleAddress), AllowList.Role.None);

try example.setGreeting("testing") {
assertTrue(false, "setGreeting should fail");
} catch {} // TODO should match on an error to make sure that this is failing in the way that's expected
}

function step_setAndGetGreeting() public {
ExampleHelloWorld example = new ExampleHelloWorld();
address exampleAddress = address(example);

assertRole(helloWorld.readAllowList(exampleAddress), AllowList.Role.None);
helloWorld.setEnabled(exampleAddress);
assertRole(helloWorld.readAllowList(exampleAddress), AllowList.Role.Enabled);

string memory greeting = "testgreeting";
example.setGreeting(greeting);
assertEq(example.sayHello(), greeting);
}
}
130 changes: 85 additions & 45 deletions contracts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"release:prepare": "rm -rf ./node_modules && npm install && npm run build"
},
"dependencies": {
"@openzeppelin/contracts": "^4.9.6"
"@openzeppelin/contracts": "^4.9.6",
"solc": "^0.8.27"
},
"engines": {
"npm": ">7.0.0",
Expand Down
Empty file removed contracts/scripts/.gitkeep
Empty file.
15 changes: 15 additions & 0 deletions contracts/scripts/deployExampleHelloWorld.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ethers } from "hardhat"
import { ExampleHelloWorld } from "typechain-types"

const main = async (): Promise<any> => {
const contract: ExampleHelloWorld = await ethers.deployContract("ExampleHelloWorld")
await contract.waitForDeployment()
console.log(`Contract deployed to: ${contract.target}`)
}

main()
.then(() => process.exit(0))
.catch(error => {
console.error(error)
process.exit(1)
})
Loading
Loading