B L O C K C H A I N P L A T S
cách tạo hợp đồng thông minh (smart contract) trên Ethereum

Hợp đồng thông minh thực sự có tiềm năng để có thể cách mạng hóa cách mọi người và doanh nghiệp tương tác. Tuy nhiên, công nghệ này đang trong thời kỳ sơ khai nên nhiều nhà phát triển phần mềm chưa hiểu rõ về cách tạo và thực thi các hợp đồng thông minh.
Bài viết hôm nay, BlockChain Plats sẽ hướng dẫn bạn cách xây dựng hợp đồng thông minh trên nền tảng chuỗi khối Ethereum.

Ethereum – một nền tảng để xây dựng các ứng dụng phi tập trung

Có một số nền tảng blockchain cho phép các nhà phát triển tạo và thực thi các hợp đồng thông minh, nhưng chúng tôi sẽ chọn Ethereum, nền tảng lớn nhất và trưởng thành nhất được tạo riêng cho mục đích này. Đây là nền tảng blockchain đầu tiên có thể thực thi mã tùy ý, vì vậy về mặt lý thuyết, bạn có thể chạy bất kỳ chương trình nào trên Ethereum.
Chuỗi khối Ethereum là một cơ sở hạ tầng toàn cầu phân tán mạnh mẽ cho phép bạn hoàn thành các dự án khác nhau với sự trợ giúp của các hợp đồng thông minh.

Tạo tiền điện tử của riêng bạn

Ethereum cho phép bạn tạo token có thể giao dịch. Các mã thông báo này sử dụng API đồng coin tiêu chuẩn, có nghĩa là chúng tương thích với bất kỳ ví nào trên chuỗi khối Ethereum.

Gây quỹ

Bạn có thể sử dụng các hợp đồng thông minh để gây quỹ trên chuỗi khối Ethereum. Bạn có thể tạo một hợp đồng thông minh chỉ định mục tiêu và thời hạn để nếu bạn không đạt được mục tiêu này, tất cả các khoản đóng góp sẽ tự động được trả lại cho các nhà tài trợ mà không có bất kỳ khoản hoa hồng hoặc tranh chấp nào.

Xây dựng tổ chức ảo

Bạn có thể viết một hợp đồng thông minh tạo ra một tổ chức dựa trên blockchain; sau đó bạn có thể thêm mọi người vào tổ chức của mình và đặt quy tắc bỏ phiếu. Các thành viên trong tổ chức của bạn sẽ có thể bỏ phiếu và nếu đạt được số phiếu yêu cầu, hợp đồng thông minh của bạn sẽ tự động thực thi.

Phát triển các ứng dụng phi tập trung

Ethereum cho phép bạn xây dựng các ứng dụng phi tập trung có khả năng chịu lỗi và bảo mật mang lại sự minh bạch và loại bỏ các bên trung gian.

Ethereum - một nền tảng để xây dựng các ứng dụng phi tập trung

Cách nền tảng Ethereum thực thi các hợp đồng thông minh

Trước khi đi sâu vào xây dựng hợp đồng thông minh Ethereum, bạn nên hiểu rõ ràng về những gì nằm dưới lớp vỏ của nền tảng blockchain Ethereum và cách nó thực thi chính xác các hợp đồng thông minh.

Máy ảo Ethereum (EVM)

Để có thể phát triển đa dạng các loại token, Ethereum đã phát triển EVM, một máy ảo đặc biệt có chức năng thông dịch cho hợp ngữ. Chức năng của EVM bị hạn chế hơn so với các máy ảo tương tự; ví dụ, nó không thể thực hiện các cuộc gọi hoặc yêu cầu bị trì hoãn trên internet hoặc tạo ra các số ngẫu nhiên, vì vậy nó chỉ đơn giản là một máy trạng thái. Viết chương trình bằng hợp ngữ không có ý nghĩa gì, vì vậy Ethereum cần một ngôn ngữ lập trình cho EVM.

Solidity

Solidity là ngôn ngữ hợp đồng thông minh trên Ethereum. Đó là một ngôn ngữ lập trình có mục đích chung được phát triển trên EVM. Cũng giống như các ngôn ngữ hướng đối tượng khác, Solidity sử dụng một lớp ( hợp đồng ) và các phương thức xác định nó. Về mặt lý thuyết, Solidity cho phép bạn thực hiện các phép tính tùy ý, nhưng mục đích chính của nó là gửi và nhận các mã thông báo kỹ thuật số cũng như các trạng thái lưu trữ. Về mặt cú pháp, Solidity chịu ảnh hưởng của JavaScript, C ++ và Python nên các lập trình viên có kinh nghiệm có thể hiểu cú pháp của nó một cách dễ dàng.
Để viết hợp đồng thông minh Ethereum đúng cách, bạn nên đọc kỹ tài liệu để tìm hiểu thêm về Solidity và cách lập trình với nó.

Gas

Trên chuỗi khối Ethereum, mỗi hợp đồng thông minh được xử lý bởi một người khai thác và kết quả của hoạt động này là một khối được thêm vào chuỗi khối Ethereum. Người khai thác phải được khen thưởng cho những nỗ lực của họ, vì vậy việc thực hiện bất kỳ hợp đồng thông minh nào trên EVM đều yêu cầu một khoản thanh toán cố định được gọi là gas . Bạn nên chỉ định số phí gas bạn muốn chi tiêu để thực hiện bất kỳ hợp đồng thông minh nào bạn tạo. Hợp đồng thông minh càng phức tạp thì càng cần nhiều phí hơn.

Hướng dẫn chi tiết cách tạo hợp đồng thông minh trên Ethereum

Đã đến lúc bắt tay vào làm việc và xây dựng một hợp đồng thông minh!

Chúng tôi đã quyết định phát triển một hợp đồng thông minh Ethereum cơ bản cho một thị trường dựa trên blockchain, nhưng bạn có thể đưa ra ý tưởng của riêng mình cho các hợp đồng thông minh.
Để triển khai hợp đồng thông minh Ethereum, bạn cần có bộ công cụ sau:

Node.js

Một môi trường thời gian chạy JavaScript để lập trình phía máy chủ. Bạn cần Node.js để kiểm tra chức năng của hợp đồng thông minh Ethereum của mình và đảm bảo nó hoạt động đúng và an toàn. Cùng với Node.js, bạn nên cài đặt một trình quản lý gói như Yarn .

Truffle 

Một khung phát triển Ethereum phổ biến cho phép bạn viết và thử nghiệm các hợp đồng thông minh. Truffle được viết bằng JavaScript và chứa một trình biên dịch cho ngôn ngữ lập trình Solidity. Truffle Сontract là một thư viện JavaScript hỗ trợ nhập các hợp đồng thông minh đã biên dịch.

Ganache CLI

Một ứng dụng gọi thủ tục từ xa (RPC) của Ethereum trong khuôn khổ Truffle; trước đây được gọi là TestRPC.

Web3.js

Một API JavaScript Ethereum giao tiếp với mạng Ethereum thông qua các lệnh gọi RPC.

Parity 

Một ứng dụng khách Ethereum nhanh chóng và an toàn để quản lý tài khoản, mã thông báo, v.v.

Visual Studio Code 

Một trình soạn thảo mã chức năng; trên thực tế, bạn có thể sử dụng bất kỳ trình soạn thảo nào khác.

Hướng dẫn từng bước để xây dựng hợp đồng thông minh trên Ethereum

Viết một hợp đồng thông minh trên Ethereum có vẻ đơn giản, nhưng bạn nên đảm bảo hợp đồng của mình hoạt động bình thường và không có lỗ hổng, vì vậy chúng tôi khuyên bạn nên bao gồm tất cả logic bằng các bài kiểm tra tự động.

Chúng tôi sẽ chia hướng dẫn hợp đồng thông minh này thành bốn bước. Trong ba bước đầu tiên, chúng tôi sẽ viết và kiểm tra mã, trong khi ở bước cuối cùng, chúng tôi sẽ triển khai hợp đồng trên chuỗi khối Ethereum.

Bước # 1: Giới thiệu hai bên tham gia hợp đồng thông minh Ethereum

Bất kỳ hợp đồng thông minh nào đều được ký kết bởi hai bên. Vì trong hợp đồng thông minh sẽ bao gồm:

– Khách hàng, người cần thực hiện một số dịch vụ

– Người giao nhiệm vụ, người hoàn thành một nhiệm vụ và được trả tiền cho nó..

Khách hàng trả tiền cho người giao việc để hoàn thành một nhiệm vụ, vì vậy bạn cũng nên thêm số tiền thanh toán vào hợp đồng thông minh; chúng tôi gọi nó là payAmount .

Trước khi mã hóa hai vai trò này và số tiền thanh toán vào hợp đồng thông minh, hãy viết một bài kiểm tra đơn vị tự động bằng JavaScript:

const OddjobPayContract = artifacts.require('OddjobPayContract')

contract('OddjobPayContract', accounts => {
  const client   = accounts[1]
  const tasker   = accounts[2]

  describe('client property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.client()).to.equal(client)
    })
  })

  describe('tasker property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.tasker()).to.equal(tasker)
    })
  })

  describe('payAmount property', () => {
    it('is initialized with 0 after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      const payAmount = await deployedContract.payAmount()
      expect(payAmount.toNumber()).to.equal(0)
    })
  })
})

Bây giờ đã đến lúc thực hiện chính xác cùng một logic để viết hợp đồng thông minh thực tế với Solidity:

pragma solidity ^0.4.4;

contract OddjobPayContract {
  address public client;
  address public tasker;

  uint256 public payAmount;

  constructor (address _client, address _tasker) public {
    client = _client;
    tasker = _tasker;

    payAmount = 0;
  }
}

Để tìm hiểu xem mã Solidity của bạn có đúng hay không, hãy chạy kiểm tra trong Truffle bằng cách sử dụng mã này (nó giống nhau cho cả ba bước):

const OddjobPayContract = artifacts.require('OddjobPayContract')

module.exports = (deployer, _, accounts) => {
  deployer.deploy(OddjobPayContract, accounts[1], accounts[2], { from: accounts[0] })
}

Hợp đồng thông minh phải vượt qua các bài kiểm tra, nếu không sẽ có lỗi trong mã của bạn.

Bước # 2: Cho phép khách hàng chuyển tiền vào hợp đồng thông minh

Hợp đồng thông minh hoạt động giống như một tài khoản riêng biệt có thể gửi tiền cho người điều khiển hoặc gửi lại cho khách hàng. Nhưng trước tiên, khách hàng phải có khả năng gửi tiền vào hợp đồng thông minh. Tại bước này, bạn cần thêm chức năng này vào hợp đồng thông minh.

Như thường lệ, hãy bắt đầu từ việc cập nhật tệp thử nghiệm. Bạn nên chỉ định rằng không ai ngoại trừ khách hàng có thể chuyển tiền vào một hợp đồng thông minh và không ai có thể tăng số tiền thanh toán:

const OddjobPayContract = artifacts.require('OddjobPayContract')

const Web3 = require('web3')

const web3 = new Web3(
  new Web3.providers.HttpProvider(
    'http://localhost:8545'
  )
)

const getRandomItem = array => (
  array[Math.floor(Math.random() * array.length)]
)

contract('OddjobPayContract', accounts => {
  const client   = accounts[1]
  const tasker   = accounts[2]

  const unknownAccount = getRandomItem(accounts.slice(3))

  describe('client property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.client()).to.equal(client)
    })
  })

  describe('tasker property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.tasker()).to.equal(tasker)
    })
  })

  describe('payAmount property', () => {
    it('is initialized with 0 after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      const payAmount = await deployedContract.payAmount()
      expect(payAmount.toNumber()).to.equal(0)
    })
  })

  describe('payable fallback', () => {
    describe('msg.sender validation', () => {
      it('deployer can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: deployer, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('tasker can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: tasker, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('unknown account can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: unknownAccount, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('only client can increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: client, value: web3.toWei(5, 'ether')
          }).then(() => done()).catch(() => done('e'))
        })()
      })
    })

    it('increases pay amount', async () => {
      const deployedContract = await OddjobPayContract.deployed()

      const payAmountWeiBefore = await deployedContract.payAmount()
      const payAmountBefore = web3.fromWei(payAmountWeiBefore, 'ether')

      await deployedContract.sendTransaction({
        from: client, value: web3.toWei(5, 'ether')
      })

      const payAmountWeiAfter = await deployedContract.payAmount()
      const payAmountAfter = web3.fromWei(payAmountWeiAfter, 'ether')

      expect(payAmountAfter - payAmountBefore).to.equal(5)
    })
  })
})

Bây giờ, hãy cập nhật hợp đồng thông minh bằng cách thêm mã cho phép khách hàng chuyển tiền vào hợp đồng đó:

pragma solidity ^0.4.4;

contract OddjobPayContract {
  address public client;
  address public tasker;

  uint256 public payAmount;

  constructor (address _client, address _tasker) public {
    client = _client;
    tasker = _tasker;

    payAmount = 0;
  }

  function () public payable {
    require(client == msg.sender);
    payAmount += msg.value;
  }
}

Đừng quên chạy các bài kiểm tra đối với hợp đồng thông minh để kiểm tra xem mọi thứ có ổn không.

Bước # 3: Cho phép hợp đồng thông minh chuyển tiền cho người điều khiển

Cuối cùng, hợp đồng thông minh của bạn phải có khả năng tự động gửi tiền cho người giao nhiệm vụ ngay sau khi khách hàng xác nhận rằng nhiệm vụ đã được hoàn thành. Để triển khai chức năng này, chúng tôi cần giới thiệu một vai trò mới trong hợp đồng thông minh – người triển khai, là một ứng dụng web trên thị trường blockchain của bạn – và chỉ định rằng chỉ người triển khai mới có thể bắt đầu chuyển tiền cho người tác nghiệp. Ngoài ra, hãy đảm bảo rằng payAmount bị vô hiệu hóa sau khi nó đã được gửi đến một tác vụ.

Đầu tiên hãy thực hiện tất cả logic này trong các bài kiểm tra; bạn phải làm cho người triển khai hoặc bất kỳ bên thứ ba nào khác không thể kích hoạt chuyển payAmount từ hợp đồng thông minh sang người giao nhiệm vụ. Ở bước này, bạn sẽ nhận được một tệp kiểm tra dài và chi tiết trông giống như sau:

const OddjobPayContract = artifacts.require('OddjobPayContract')

const Web3 = require('web3')

const web3 = new Web3(
  new Web3.providers.HttpProvider(
    'http://localhost:8545'
  )
)

const getRandomItem = array => (
  array[Math.floor(Math.random() * array.length)]
)

contract('OddjobPayContract', accounts => {
  const deployer = accounts[0]
  const client   = accounts[1]
  const tasker   = accounts[2]

  const unknownAccount = getRandomItem(accounts.slice(3))

  describe('deployer property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.deployer()).to.equal(deployer)
    })
  })

  describe('client property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.client()).to.equal(client)
    })
  })

  describe('tasker property', () => {
    it('is initialized after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      expect(await deployedContract.tasker()).to.equal(tasker)
    })
  })

  describe('payAmount property', () => {
    it('is initialized with 0 after deployment', async () => {
      const deployedContract = await OddjobPayContract.deployed()
      const payAmount = await deployedContract.payAmount()
      expect(payAmount.toNumber()).to.equal(0)
    })
  })

  describe('payable fallback', () => {
    describe('msg.sender validation', () => {
      it('deployer can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: deployer, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('tasker can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: tasker, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('unknown account can not increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: unknownAccount, value: web3.toWei(5, 'ether')
          }).then(() => done('e')).catch(() => done())
        })()
      })

      it('only client can increase pay amount', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendTransaction({
            from: client, value: web3.toWei(5, 'ether')
          }).then(() => done()).catch(() => done('e'))
        })()
      })
    })

    it('increases pay amount', async () => {
      const deployedContract = await OddjobPayContract.deployed()

      const payAmountWeiBefore = await deployedContract.payAmount()
      const payAmountBefore = web3.fromWei(payAmountWeiBefore, 'ether')

      await deployedContract.sendTransaction({
        from: client, value: web3.toWei(5, 'ether')
      })

      const payAmountWeiAfter = await deployedContract.payAmount()
      const payAmountAfter = web3.fromWei(payAmountWeiAfter, 'ether')

      expect(payAmountAfter - payAmountBefore).to.equal(5)
    })
  })

  describe('sendPayAmountToTasker action', () => {
    describe('msg.sender validation', () => {
      it('can be triggered by deployer', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendPayAmountToTasker({ from: deployer })
            .then(() => done())
            .catch(() => done('e'))
        })()
      })

      it('can not be triggered by client', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendPayAmountToTasker({ from: client })
            .then(() => done('e'))
            .catch(() => done())
        })()
      })

      it('can not be triggered by tasker', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendPayAmountToTasker({ from: tasker })
            .then(() => done('e'))
            .catch(() => done())
        })()
      })

      it('can not be triggered by unknown account', done => {
        (async () => {
          const deployedContract = await OddjobPayContract.deployed()

          deployedContract.sendPayAmountToTasker({ from: unknownAccount })
            .then(() => done('e'))
            .catch(() => done())
        })()
      })
    })

    it('nullifies pay amount', async () => {
      const deployedContract = await OddjobPayContract.new(
        client, tasker, { from: deployer }
      )

      await deployedContract.sendTransaction({
        from: client, value: web3.toWei(5, 'ether')
      })

      const payAmountWeiBefore = await deployedContract.payAmount()
      const payAmountBefore = web3.fromWei(payAmountWeiBefore, 'ether')

      await deployedContract.sendPayAmountToTasker({ from: deployer })

      const payAmountWeiAfter = await deployedContract.payAmount()
      const payAmountAfter = web3.fromWei(payAmountWeiAfter, 'ether')

      expect(payAmountAfter - payAmountBefore).to.equal(-5)
      expect(payAmountAfter.toNumber()).to.equal(0)
    })
  })
})

Bây giờ bạn nên thêm logic này vào chính hợp đồng thông minh: giới thiệu một người triển khai và cho phép người đó chuyển tiền cho một người giao việc. Hợp đồng thông minh đầy đủ mà chúng tôi đã xây dựng trông như sau:

pragma solidity ^0.4.4;

contract OddjobPayContract {
  address public deployer;

  address public client;
  address public tasker;

  uint256 public payAmount;

  constructor (address _client, address _tasker) public {
    deployer = msg.sender;

    client = _client;
    tasker = _tasker;

    payAmount = 0;
  }

  function () public payable {
    require(client == msg.sender);
    payAmount += msg.value;
  }

  function sendPayAmountToTasker() public {
    require(deployer == msg.sender);

    // transfer pay amount to tasker
    tasker.transfer(payAmount);

    // nullify pay amount manually
    payAmount = 0;
  }
}

Cuối cùng, để kiểm tra xem hợp đồng thông minh không có lỗi nào, hãy kiểm tra nó trong Truffle.

Bước # 4: Triển khai hợp đồng thông minh của bạn

Hợp đồng thông minh trong Solidity đã sẵn sàng nên còn một bước cuối cùng – biên dịch và sau đó triển khai nó. Vì đây là một hướng dẫn, nên việc triển khai hợp đồng trên mạng Ethereum không có ý nghĩa gì, vì vậy chúng tôi sẽ thực hiện nó trong Ropsten, một mạng thử nghiệm phổ biến cho Ethereum.
Đây thực sự là bước khó nhất trong hướng dẫn của chúng tôi, vì vậy chúng tôi sẽ chia nó thành nhiều bước phụ:

Tạo ví Ethereum

Có ba vai trò trong các hợp đồng thông minh của chúng tôi, vì vậy để kiểm tra xem mọi thứ có hoạt động hay không, chúng tôi cần tạo ba ví trên Ethereum: cho khách hàng, cho người tác vụ và cho người gửi tương ứng. Không cần phải nói, ví của người triển khai sẽ giống nhau đối với tất cả các hợp đồng thông minh trong thị trường phi tập trung của chúng tôi, trong khi ví của khách hàng và người triển khai sẽ khác nhau đối với mỗi hợp đồng thông minh.

Nhận Ether trên Ropsten testnet

Các ví Ethereum mới được tạo có số dư bằng 0 ether, vì vậy để thực hiện hợp đồng thông minh, chúng ta cần nhận được một số ether. Điều này khá đơn giản, vì chúng tôi đang triển khai hợp đồng thông minh trên mạng thử nghiệm Ropsten.

Có một số cách để nhận ether thử nghiệm miễn phí. Hãy sử dụng plugin Metamask (chúng tôi đã sử dụng phiên bản cho Google Chrome). Metamask là một phần mở rộng của Ethereum cho phép bạn làm việc với các ứng dụng phi tập trung ngay trong trình duyệt của mình. Nhập tài khoản Metamask và thêm ba ví vào đó. Sau đó, truy cập https://faucet.metamask.io/ và yêu cầu ether miễn phí; tuy nhiên, hãy thận trọng vì bạn chỉ có thể nhận được một số ether miễn phí có hạn cho mỗi tài khoản.
Logic của hợp đồng thông minh của chúng tôi hoạt động như thế này: tiền được chuyển từ khách hàng sang hợp đồng thông minh, sau đó tự động được gửi đến người giao nhiệm vụ. Do đó, chúng tôi cần eth của mình trong ví của khách hàng.

Biên dịch hợp đồng thông minh với Truffle

Chúng tôi đã xây dựng một hợp đồng thông minh được viết bằng Solidity, nhưng nó sẽ được chuyển thành tệp .json để triển khai. Sử dụng Truffle để biên dịch hợp đồng thông minh của bạn; nó sẽ tạo một tệp .json mà bạn có thể gọi bất cứ thứ gì bạn muốn (chúng tôi gọi nó là OddjobPayContract.json).

Chạy tập lệnh triển khai

Để triển khai hợp đồng thông minh của bạn trên Ropsten testnet, chúng tôi đã tạo tập lệnh sau bằng JavaScript:

const Web3 = require('web3')
const contract = require('truffle-contract')
const SmartContract = contract(require('./build/contracts/OddjobPayContract'))

const deployer = '0x2Af1552C6b02a1C8eE6B8A9175867198EE7DeCA1'
const client   = '0x4baB642a718738504871e4e9399C8F103aE0A23E'
const tasker   = '0xAcF1006EA19f9ed5b276204036010687C1A79683'

const web3Provider = new Web3.providers.HttpProvider(
  'http://10.10.11.75:8545' // address of the Parity node
)

const web3 = new Web3(web3Provider)

web3.eth.getAccounts(error => {
  if (error) {
    throw new Error(`
      Error while fetching accounts from RPC!
      Check RPC address! The problem may be there!
    `)
  }
})

const fetchBalanceByAddress = async address => {
  return new Promise(resolve => {
    web3.eth.getBalance(address, (_, balance) => {
      resolve(web3.fromWei(balance, 'ether').toString())
    })
  })
}

const printBalancesToConsole = async () => {
  const deployerBalance = await fetchBalanceByAddress(deployer)
  const clientBalance   = await fetchBalanceByAddress(client)
  const taskerBalance   = await fetchBalanceByAddress(tasker)

  console.log(`Deployer: ${deployerBalance}; Client: ${clientBalance}; Tasker: ${taskerBalance}`)
}

const run = async () => {
  await printBalancesToConsole()

  SmartContract.setProvider(web3Provider)

  const smartContract = await SmartContract.new(
    client, tasker, { gas: 1000000, from: deployer }
  )

  await printBalancesToConsole()

  await smartContract.sendTransaction({ from: client, value: web3.toWei(0.1, 'ether') })

  await printBalancesToConsole()

  await smartContract.sendPayAmountToTasker({ from: deployer })

  await printBalancesToConsole()
}

run()

Thực thi hợp đồng thông minh của bạn

Sau khi hợp đồng thông minh của bạn được triển khai, bạn có thể thực thi nó. Để làm điều này, bạn cần chỉ định ví cho máy khách, người giao nhiệm vụ và người triển khai cũng như phần thưởng cho người vận hành.

Hãy nhớ rằng việc triển khai hợp đồng thông minh sẽ tốn một lượng phí gas cụ thể, vì vậy hãy đảm bảo chỉ định lượng gas bạn đưa vào hợp đồng thông minh của mình. Nếu một hợp đồng thông minh yêu cầu ít phí gas hơn bạn cung cấp, phần còn lại sẽ được trả lại cho bạn. Nhưng nếu việc thực hiện một hợp đồng đòi hỏi nhiều phí gas hơn, nó sẽ chỉ đơn giản là thất bại với lỗi “hết gas”. Bạn có thể sử dụng eth_estimateGasphương pháp ước tính lượng phí gas cần thiết để triển khai hợp đồng thông minh của bạn. Thật không may, điều này chỉ cung cấp một ước tính và lượng khí thực tế có thể cao hơn, vì vậy tốt hơn là nên bao gồm nhiều phí gas hơn. Hãy nhớ rằng giới hạn gas bạn cung cấp càng thấp thì mức độ ưu tiên mà hợp đồng thông minh của bạn sẽ có trên mạng Ethereum càng thấp (trừ khi bạn tăng giá gas) và có thể web3 sẽ trả về lỗi cho bạn biết rằng giao dịch của bạn không có ‘ t được khai thác trong vòng 50 khối. Trong trường hợp này, bạn nên nạp thêm khí hoặc chỉ cần sử dụng giới hạn phí gas từ khối mới nhất được khai thác thành công .

Cuối cùng, thực hiện hợp đồng thông minh. Trong một số thời điểm, bạn có thể kiểm tra số dư trong cả ba ví để tìm hiểu xem mọi thứ có hoạt động hay không.

Chúc bạn thành công!

>> Xem thêm: Hướng dẫn lập trình phát triển Bitcoin (BTC) mới nhất và đầy đủ nhất

Bài viết liên quan

Leave a Comment

Là một nhà phát triển có nhiều kinh nghiệm, Blockchain Plats thúc đẩy sự thành công của các doanh nghiệp thông qua các giải pháp tài chính, ứng dụng Blockchain và tiền điện tử sáng tạo, bảo mật và minh bạch

Liên hệ