建议和反馈

请填写你的反馈内容

以太坊区块链的简单可靠性智能合约

2020-01-21 ·1921次阅读 ·读完需要8分钟

这是使用Solidity的典型智能合约示例简单银行的修改版本,例如:https : //github.com/ScottWorks/ConsenSys-Academy-Notes/blob/master/Smart-Contracts/Simple-Bank-Exercise/simple_bank/合同/SimpleBank.sol


但是,与其像原始示例那样奖励所有注册的客户,这意味着银行合同应预先持有所有以太币以获取奖励,它只向3个第一位客户分别奖励10个以太币。这样,它就可以进行操作,而不会耗尽以太币以获取奖励。


除注册外,客户还可以存入和提取以太币并读取其余额。最后,合同还提供了另一种检查合同中所有存款的总余额的方法。


可以从以下网址获得此练习的完整源代码:https : //github.com/rogargon/simple_bank


要求

对于本练习,根需求和Node及其驱动程序管理器npm。要安装它们,请遵循以下指示:https : //www.npmjs.com/get-npm


然后,我们将使用Truffle智能合约开发框架来引导开发过程,并负责部署和测试。


要安装Truffle,一旦有了Node和npm:


npm install -g truffle


注意:如果在Windows上运行Truffle,则可能存在一些命名冲突,这些冲突可能会阻止Truffle正确执行,具体说明如下:https : 

//truffleframework.com/docs/advanced/configuration#resolving-naming-conflicts-on-windows


简单银行智能合约开发

为了引导开发过程,我们将使用Truffle生成智能合约项目的框架。为此,请为您的项目创建一个目录,移至该目录并按照以下步骤执行Truffle初始化:


mkdir simple_bankcd simple_banktruffle init


这会生成一个类似于https://truffleframework.com/docs/getting_started/project#exploring-the-project中描述的智能项目结构。


在我们的例子中,这是一个空项目,没有像MetaCoin.sol这样的初始示例合同


因此,首先,我们在“ contracts /”文件夹中创建一个名为“ SimpleBank.sol”的新文件,其内容如下:

pragma solidity ^0.5.8;contract SimpleBank {
    uint8 private clientCount;
    mapping (address => uint) private balances;
    address public owner;
  // Log the event about a deposit being made by an address and its amount
    event LogDepositMade(address indexed accountAddress, uint amount);
    // Constructor is "payable" so it can receive the initial funding of 30, 
    // required to reward the first 3 clients
    constructor() public payable {        require(msg.value == 30 ether, "30 ether initial funding required");        /* Set the owner to the creator of this contract */
        owner = msg.sender;
        clientCount = 0;
    }
    /// @notice Enroll a customer with the bank, 
    /// giving the first 3 of them 10 ether as reward
    /// @return The balance of the user after enrolling
    function enroll() public returns (uint) {        if (clientCount < 3) {
            clientCount++;
            balances[msg.sender] = 10 ether;
        }
        return balances[msg.sender];
    }
    /// @notice Deposit ether into bank, requires method is "payable"
    /// @return The balance of the user after the deposit is made
    function deposit() public payable returns (uint) {
        balances[msg.sender] += msg.value;
        emit LogDepositMade(msg.sender, msg.value);
        return balances[msg.sender];
    }
    /// @notice Withdraw ether from bank
    /// @return The balance remaining for the user
    function withdraw(uint withdrawAmount) public returns (uint remainingBal) {        // Check enough balance available, otherwise just return balance
        if (withdrawAmount <= balances[msg.sender]) {
            balances[msg.sender] -= withdrawAmount;
            msg.sender.transfer(withdrawAmount);
        }
        return balances[msg.sender];
    }
    /// @notice Just reads balance of the account requesting, so "constant"
    /// @return The balance of the user
    function balance() public view returns (uint) {        return balances[msg.sender];
    }
    /// @return The balance of the Simple Bank contract
    function depositsBalance() public view returns (uint) {        return address(this).balance;
    }}

部署方式

要指示Truffle部署先前的合同,应将以下脚本“ 2_deploy_contracts.js”添加到“ migrations /”文件夹中。部署应包括向构造函数发送30个以太币(相当于30000000000000000000 wei),标记为“应付”以在合同中接收此初始余额。

var SimpleBank = artifacts.require("./SimpleBank.sol");module.exports = function(deployer) {
  deployer.deploy(SimpleBank, { value: 30000000000000000000 });};

然后,我们会将合同部署到松露提供的本地开发网络中。启动此测试网络的命令是:

truffle develop

这将以10个示例帐户从http://127.0.0.1:9545开始Truffle Develop。

然后,在另一个终端中编译合同(松露开发使网络继续运行):

truffle compile

如果没有错误,则可以将合同部署到本地开发网络。要配置此网络,文件“ truffle-config.js”应至少包含:

module.exports = {  networks: {      development: {      host: "127.0.0.1",      port: 9545,      network_id: "*",
    },
  },}

然后,触发智能合约的部署:

truffle migrate

测试中

现在可以测试以前部署的合同,以检查它是否按预期工作。我们还将使用松露进行测试。

测试也可以用Solidity或使用JavaScript编写。在我们的例子中,我们使用JavaScript,并且以下代码位于“ test /”文件夹中的“ simpleBank.test.js”文件中:

var SimpleBank = artifacts.require("./SimpleBank.sol");const ether = 10**18; // 1 ether = 1000000000000000000 weiconst reward = 10 * ether;const initialDepositsBalance = 30 * ether;contract("SimpleBank - basic initialization", function(accounts) {  const alice = accounts[1];  const bob = accounts[2];  const charlie = accounts[3];  const dave = accounts[4];
  it("should reward 3 first clients with 10 balance", async () => {    const bank = await SimpleBank.deployed();
    await bank.enroll({from: alice});    const aliceBalance = await bank.balance({from: alice});
    assert.equal(aliceBalance, reward, "initial balance is incorrect");
    await bank.enroll({from: bob});    const bobBalance = await bank.balance({from: bob});
    assert.equal(bobBalance, reward, "initial balance is incorrect");
    await bank.enroll({from: charlie});    const charlieBalance = await bank.balance({from: charlie});
    assert.equal(charlieBalance, reward, "initial balance is incorrect");
    await bank.enroll({from: dave});    const daveBalance = await bank.balance({from: dave});
    assert.equal(daveBalance, 0, "initial balance is incorrect");
    const depositsBalance = await bank.depositsBalance();
    assert.equal(depositsBalance, initialDepositsBalance, "initial balance is incorrect");
  });
  it("should deposit correct amount", async () => {    const bank = await SimpleBank.deployed();    const deposit = 2 * ether;
    const receipt = await bank.deposit({from: alice, value: web3.utils.toBN(deposit)});
    const balance = await bank.balance({from: alice});
    assert.equal(balance, reward + deposit,
        "deposit amount incorrect, check deposit method");    const depositsBalance = await bank.depositsBalance();
    assert.equal(depositsBalance, initialDepositsBalance + deposit,
        "bank deposits balance should be increased");
    const expectedEventResult = {accountAddress: alice, amount: deposit};
    assert.equal(receipt.logs[0].args.accountAddress, expectedEventResult.accountAddress,        "LogDepositMade event accountAddress property not emitted");
    assert.equal(receipt.logs[0].args.amount, expectedEventResult.amount,        "LogDepositMade event amount property not emitted");
  });});contract("SimpleBank - proper withdrawal", function(accounts) {  const alice = accounts[1];
  it("should withdraw correct amount", async () => {    const bank = await SimpleBank.deployed();    const deposit = 5 * ether;
    await bank.deposit({from: alice, value: web3.utils.toBN(deposit)});    await bank.withdraw(web3.utils.toBN(deposit), {from: alice});
    const balance = await bank.balance({from: alice});
    assert.equal(balance, deposit - deposit, "withdraw amount incorrect");
  });});contract("SimpleBank - incorrect withdrawal", function(accounts) {  const alice = accounts[1];
  it("should keep balance unchanged if withdraw greater than balance", async() => {    const bank = await SimpleBank.deployed();    const deposit = 3 * ether;
    await bank.deposit({from: alice, value: web3.utils.toBN(deposit)});    await bank.withdraw(web3.utils.toBN(deposit + 1*ether), {from: alice});
    const balance = await bank.balance({from: alice});
    assert.equal(balance, deposit, "balance should be kept intact");
  });});contract("SimpleBank - fallback works", function(accounts) {  const alice = accounts[1];
  it("should revert ether sent to this contract through fallback", async() => {    const bank = await SimpleBank.deployed();    const deposit = 3 * ether;
    try {      await bank.send(web3.utils.toBN(deposit), {from: alice});
    } catch(e) {
      assert(e, "Error: VM Exception while processing transaction: revert");
    }
    const depositsBalance = await bank.depositsBalance();
    assert.equal(depositsBalance, initialDepositsBalance, "balance should be kept intact");
  });});

要使用松露运行先前的测试,请执行以下操作:

truffle test

如果一切正常,则应该是预期的输出:

Using network 'development'.
  Contract: SimpleBank - basic initialization
    ✓ should reward 3 first clients with 10 balance (168ms)
    ✓ should deposit correct amount (63ms)
  Contract: SimpleBank - proper withdrawal
    ✓ should withdraw correct amount (63ms)
  Contract: SimpleBank - incorrect withdrawal
    ✓ should keep balance unchanged if withdraw greater than balance (73ms)
  Contract: SimpleBank - fallback works
    ✓ should revert ether sent to this contract through fallback
  5 passing (482ms)

可以从以下网址获得此练习的完整源代码:https : //github.com/rogargon/simple_bank

与合同互动

要在测试环境中以交互方式测试合同,而无需花费任何时间,我们可以使用Remix在线IDE工具。无需安装任何东西,只需浏览至:https : //remix.ethereum.org

只需在Remix中复制并粘贴SimpleBank.sol的内容即可。不应有任何编译错误,因此我们可以切换到“部署”选项卡,以从第一个可用帐户中预加载100以太币的可用帐户中,将其部署到“ JavaScript VM”模拟的以太坊区块链中。在部署之前,我们应该将部署交易的价值设置为30以太,以便我们提供所需的初始奖励资金,如屏幕截图所示:

混音SimpleBank部署

部署后,我们可以看到部署帐户中的以太币数量已减少到少于70个以太币,这是由于30个以太币已转移到银行合同中,再加上交易气体成本。我们还可以在“已部署合同”部分中查看合同,如下所示:

现在,我们可以开始与银行合同进行交互了。选择第二个帐户后,我们可以通过单击已部署合同中的“注册”按钮来注册它。这将向新客户奖励10以太币,尽管它会存储在合同中,所以由于注册交易的成本,帐户的余额应略低于最初的100以太币,如图所示:

奖励后,第二个帐户在银行中有10个以太币。因此,它的一部分可以撤回。要提取一半,我们可以在关联的输入框中指定要提取的金额为5000000000000000000,以wei表示且等于5 ether以后,使用“ withdraw”按钮。这样做之后,第二个帐户持有的以太币数量应略低于105个以太币,如屏幕截图所示:混音SimpleBank提款

最后,我们可以检查银行第二个帐户的余额是否是奖励的剩余部分。我们使用蓝色的“天平”按钮检查天平,该按钮对应于没有气体费用的读取操作。结果应为5000000000000000000 wei,即5以太,如下所示:

您可以继续尝试Remix并与合同进行交互。例如,获取合同中所有存款的余额(现在应该为25以太),或注册其他帐户。


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

构建以太坊DAPP游戏的区块链应用

以太坊是通用区块链,更适合通过高级脚本(也称为智能合约)来描述业务逻辑。以太坊的设计具有更广阔的视野,它是一台试图将区块链的功能与一台图灵完备的合约引擎相结合的分散式或世界计算机,作为一种信任机器。尽......
BTC · 2020-02-26
312阅读 · 0赞赏 · 0问答

从以太坊到超级账本的区块链演变和阶段概述

区块链将在去中心化的同时提高业务绩效,从而成为全球许多行业和市场中占主导地位的游戏规则改变技术。它在现代供应链管理中的实施产生了惊人的结果,整个链实现了自动化,同时消除了冗余和中间商。截至撰写本文时,......
区块链网 · 2020-02-26
350阅读 · 0赞赏 · 0问答

区块链钱包系统开发方案,多币种钱包开发

区块链钱包系统开发方案,多币种钱包开发怎么样理解钱包呢?简单讲它是连接区块链的一个入口。目前比较成熟的公链,如比特币、以太坊都有很多钱包可以选择。一般钱包需要完全访问你的用户资产,也就是会要求你输入私......
T13823153201 · 2020-02-26
364阅读 · 0赞赏 · 0问答

以太坊矿机简单的介绍

以太坊挖机:它们是什么以及如何设置它们,在开始以太坊采矿装备之前,让我们快速了解一下到目前为止对以太坊和采矿以太坊的了解。什么是以太坊如何开采以太坊以太坊采矿硬件 以太坊矿机的组成如果您打算......
区块链论坛 · 2020-02-26
374阅读 · 0赞赏 · 0问答

EDG上线追币交易所,波卡生态迎来爆发还会远吗?

2019 年,区块链领域最受瞩目的明星项目就是波卡(Polkadot)了。 它不仅被认为是区块链在继比特币、以太坊和EOS之后又一个划时代的项目,甚至被认为是Web3.0 ——下一......
追币视点 · 2020-02-25
460阅读 · 0赞赏 · 0问答

如何挖以太坊?

挖矿基本上是利用您正在使用的设备的计算能力与电力相结合在区块链上查找区块的过程。挖矿是在区块链上验证和批准交易的过程。矿工通过交换获得的奖励是加密货币令牌(硬币)的奖励。对于比特币区块链,奖励是比特币......
论坛咸鸟 · 2020-02-25
513阅读 · 0赞赏 · 0问答

16054

LK币

36

粉丝

406

笔记

感谢"区块链社区"

这篇精彩的笔记,目前已经帮助

  • 0
  • 1
  • 9
  • 2
  • 1
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!