0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Truffle on wsl

Last updated at Posted at 2022-01-29

Originally

I have copied the code from the following book.
Hands-On Smart Contract Development with Solidity and Ethereum

Environment

  • Windows 11
  • wsl2
  • Ubuntu 18.04
  • nvm : 0.39.0
  • node : 16.13.2
  • npm : 8.1.2
  • Truffle v5.4.30 (core: 5.4.30)
  • Solidity - 0.8.11 (solc-js)
  • Node v16.13.2
  • Web3.js v1.5.3

Prepare

wsl2
https://docs.microsoft.com/en-us/windows/wsl/install

open ubuntu on wsl.

nvm
https://github.com/nvm-sh/nvm

Install Truffle

command
# sometime you should install gcc and package before.
# sudo apt install g++-7 libstdc++-7-dev
nvm install 16.13.2 # DO NOT USE >=17.0.0
nvm use 16.13.2
npm i -g truffle  # DO NOT USE sudo

Create Project and Greeter Contract

command
mkdir greeter
cd greeter
truffle init
truffle create contract Greeter
truffle create test Greeter
truffle create migration Greeter

Install prettier for vscode

command
npm install --save-dev prettier prettier-plugin-solidity
code --install-extension esbenp.prettier-vscode
code --install-extension JuanBlanco.solidity
.vscode/settings.json
{
  "editor.formatOnSave": true,
  "solidity.formatter": "prettier",
  "[solidity]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}
prettier.config.js
module.exports = {
  overrides: [
    {
      files: "*.sol",
      options: {
        printWidth: 80,
        tabWidth: 2,
        useTabs: false,
        singleQuote: false,
        bracketSpacing: false,
        explicitTypes: "always",
      },
    },
  ],
};

Edit Migration File

Edit migration file. It may in ./migraionts folder

migrations/12345678_greeter.js
const Greeter = artifacts.require("Greeter");
module.exports = function(_deployer) {
  _deployer.deploy(Greeter);
};

Run First Test

command
truffle test
# Using network 'test'.
#Compiling your contracts...
#===========================
#> Compiling ./contracts/Greeter.sol
#> Compiling ./contracts/Migrations.sol
#> Compilation warnings encountered:
#> Artifacts written to /tmp/test--2064-vQs8uxlslsyw
#> Compiled successfully using:
#   - solc: 0.8.11+commit.d7f03943.Emscripten.clang
#
#  Contract: Greeter
#    ✓ should assert true
#
#  1 passing (20ms)

If you have some compile errors, please read this article.

Hello World!

contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
// remove constructor
contract Greeter {
  function greet() external pure returns(string memory){
    return "Hello, World!";
  }
}
test/greeter.js
const Greeter = artifacts.require("Greeter");
contract("Greeter", function (/* accounts */) {
  it("should assert true", async function () {
    await Greeter.deployed();
    return assert.isTrue(true);
  });
describe("greet()", () => {
    it("returns 'Hello, World!'", async () => {
      const greeter = await Greeter.deployed();
      const expected = "Hello, World!";
      const actual = await greeter.greet();
      assert.equal(actual, expected, "greeted with'Hello, World!'");
    })
  })
});
command
truffle test
#  Contract: Greeter
#    ✓ should assert true
#    greet()
#      ✓ returns 'Hello, World!'
#
#  2 passing (31ms)

Update Message

So far it has only returned a fixed "Hello World!", but I will try to update the message.

contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Greeter {
  string private _greeting = "Hello, World!";

  function greet() external view returns (string memory) {
    return _greeting;
  }

  function setGreeting(string calldata greeting) external {
    _greeting = greeting;
  }
}
test/greeter.js
const Greeter = artifacts.require("Greeter");
contract("Greeter", function (/* accounts */) {
  it("should assert true", async function () {
    await Greeter.deployed();
    return assert.isTrue(true);
  });
  describe("greet()", () => {
    it("returns 'Hello, World!'", async () => {
      const greeter = await Greeter.deployed();
      const expected = "Hello, World!";
      const actual = await greeter.greet();
      assert.equal(actual, expected, "greeted with 'Hello, World!'");
    });
  });
});
contract("Greeter: update greeting", function (/* accounts */) {
  it("sets greeting to passed in string", async function () {
    const greeter = await Greeter.deployed();
    const expected = "Hi there!";
    await greeter.setGreeting(expected);
    const actual = await greeter.greet();
    assert.equal(actual, expected, "greeing updated'");
  });
});
command
truffle test
#  Contract: Greeter
#    ✓ should assert true
#    greet()
#      ✓ returns 'Hello, World!'
#  Contract: Greeter: update greeting
#    ✓ sets greeting to passed in string (1060ms)```
#  3 passing (1s)

Check Ownership

Ensure that only the Owner can update messages.

contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Greeter {
  string private _greeting = "Hello, World!";
  address private _owner;

  constructor() {
    _owner = msg.sender;
  }

  modifier onlyOwner() {
    require(msg.sender == _owner, "Ownable: caller is not the owner");
    _;
  }

  function greet() external view returns (string memory) {
    return _greeting;
  }

  function setGreeting(string calldata greeting) external onlyOwner {
    _greeting = greeting;
  }

  function owner() public view returns (address) {
    return _owner;
  }
}
test/greeter.js
const Greeter = artifacts.require("Greeter");
contract("Greeter: update greeting", (accounts) => {
  describe("when  message is sent by the owner", () => {
    it("sets greeting is sent by the owner", async () => {
      const greeter = await Greeter.deployed();
      const expected = "The owner changed the mssage";
      await greeter.setGreeting(expected);
      const actual = await greeter.greet();
      assert.equal(actual, expected, "greeting updated");
    });
  });
  describe("when message is sent by another account", () => {
    it("does not set the greeting", async () => {
      const greeter = await Greeter.deployed();
      const expected = await greeter.greet();
      try {
        await greeter.setGreeting("Not the owner", { from: accounts[1] });
      } catch (err) {
        const errorMessage = "Ownable: caller is not the owner";
        assert.equal(err.reason, errorMessage, "greeting should not update");
        return;
      }
      assert(false, "greeting shoud not update");
    });
  });
});
command
truffle test
#  Contract: Greeter: update greeting
#    when  message is sent by the owner
#      ✓ sets greeting is sent by the owner (1066ms)
#    when message is sent by another account
#      ✓ does not set the greeting (1083ms)
#  2 passing (2s)

Use OpenZeppelin

Use OpenZeppelin module.

command
npm init -y
npm i openzeppelin-solidity
contracts/Greeter.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "openzeppelin-solidity/contracts/access/Ownable.sol";

contract Greeter is Ownable {
  string private _greeting = "Hello, World!";

  function greet() external view returns (string memory) {
    return _greeting;
  }

  function setGreeting(string calldata greeting) external onlyOwner {
    _greeting = greeting;
  }
}

Next Step

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?