建议和反馈

请填写你的反馈内容

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

2020-01-21 ·745次阅读 ·读完需要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)
请先登录或注册

请先登陆或注册

相关推荐

如何从私钥创建以太坊钱包地址

在本系列的第一篇文章中,我们生成了一个比特币私钥:60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2。在这里,我们将使用该......
区块链网 · 2020-01-19
701阅读 · 0赞赏 · 0问答

plasma能否解决以太坊的可扩展性问题?

plasma是一种新技术,可以解决以太坊的可扩展性问题。第二大市值的以太坊(Ethereum)试图解决Plasma和更高级的Plasma Cash的各种问题。在本文中,我们将介绍plasma的机理和好......
区块链社区 · 2020-01-14
800阅读 · 0赞赏 · 0问答

web3.js v1.0.0如何监控以太坊合约

为了使前台显示的数据与DApp中合同的数据同步,我检查了是否可以监视合约的状态。这可以通过定期获取数据来实现,但是考虑到前部负载和气体成本,我们将选择一种有效的方法。验证DApp将SetValue事件......
Blockchain · 2020-01-14
947阅读 · 0赞赏 · 0问答

以太坊挖矿初学者指南

挖矿在区块链应用中很受欢迎,围绕比特币的炒作真的不足为奇。开采比特币需要大量投资于一种非常专业的机器。它被称为ASIC矿工。ASIC是专用集成电路的缩写。简而言之,这些设备是为完成一件事情而定制的:挖......
古风 · 2020-01-13
1013阅读 · 0赞赏 · 0问答

使用Python编译,部署和调用以太坊智能合约

我们在Ubuntu 16.04上使用Python 3.5.3,并进行以下设置:pip3 install web3==4.7.2 py-solc==3.2.0python3 -m solc.instal......
HBO · 2020-01-13
939阅读 · 0赞赏 · 0问答

16052

LK币

35

粉丝

406

笔记

感谢"区块链社区"

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

  • 0
  • 0
  • 7
  • 4
  • 5
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

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

联系方式:010-67707199

ICP备案号:京ICP备18032136号

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

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

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

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

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