How to write a scalable smart contract

The unmodifiable feature of blockchain trust-based data makes it very different from traditional applications. Once published on the blockchain, it cannot be modified (it cannot be directly modified on the original contract and then republished) .

write in front

Before reading this article, you should have some understanding of Ethereum, smart contracts and Solidity language . If you don't know it yet, I suggest you read what Ethereum is first.

When smart contracts have bugs

On the one hand, it is officially due to the unmodifiable nature of smart contracts, because as long as the rules are determined, no one can modify it, and everyone can trust it. On the other hand, if there are bugs in the implementation of the rules, the tokens may be stolen, or the calls may consume a lot of gas. Then we need to fix the error.

We know that a smart contract consists of two parts: code logic and data, and code logic is the most problematic part. For example, when implementing the following contract, when writing addTen() due to hand tremor, 10 is written as 11.

pragma solidity ^0.4.18;

contract MyContract {
    mapping (address => uint256) public balanceOf;

    function setBlance(address _address,uint256 v) public {
        balanceOf[_address] = v;
    }

    function addTen(address addr) public returns (uint){
        return balanceOf[addr] + 11;
    }
}

If we find this problem after deployment and want to fix this bug, we have to redeploy the contract, but then there will be an embarrassing problem. The original contract has been used by many people. If a new contract is deployed, the old contract will Data will be lost.

Data Contract and Control Contract

So how to solve the above problem, one solution is to separate the data in the contract, use a separate contract to store the data (hereinafter referred to as the data contract), and use a separate contract to write business logic (hereinafter referred to as the control contract).
Let's see how the code does it.

pragma solidity ^0.4.18;

contract DataContract {
    mapping (address => uint256) public balanceOf;

    function setBlance(address _address,uint256 v) public {
        balanceOf[_address] = v;
    }
}

contract ControlContract {

    DataContract dataContract;

    function ControlContract(address _dataContractAddr) public {
        dataContract = DataContract(_dataContractAddr);
    }

    function addTen(address addr) public returns (uint){
        return dataContract.balanceOf(addr) + 11;
    }
}

Now we have two contracts DataContract for storing data, ControlContract for processing logic, and DataContract for reading and writing data. With this design, the data contract can be kept unchanged after updating the control contract, so that no data is lost or migrated.

read and write control

Through DataContract, we can update the contract logic separately, but you may find a new problem. The data of DataContract can be read and written not only by ControlContract, but also by other contracts. Therefore, it is necessary to add read and write control to DataContract. We add a mapping to DataContract to control which addresses can access data, and add modifiers and methods to set access. The code is as follows:

pragma solidity ^0.4.18;

contract DataContract {
    mapping (address => uint256) public balanceOf;
    mapping (address => bool) accessAllowed;

    function DataContract() public {
        accessAllowed[msg.sender] = true;
    }

    function setBlance(address _address,uint256 v) public {
        balanceOf[_address] = v;
    }

    modifier platform() {
        require(accessAllowed[msg.sender] == true);
        _;
    }

    function allowAccess(address _addr) platform public {
        accessAllowed[_addr] = true;
    }

    function denyAccess(address _addr) platform public {
        accessAllowed[_addr] = false;
    }
}

...

Subscribe to my small column to see the full code of the contract.

The deployment method is as follows:
1. First deploy the DataContract contract
2. Use the DataContract contract address as the parameter to deploy the ControlContract contract
3. Use the ControlContract contract address as the parameter to call the allowAccess method of the DataContract contract.
If you need to update the control contract (such as repairing addTen), then perform steps 2-3 again, and execute denyAccess() on the old control contract.

More

When we implement a data contract, it should contain as little logic as possible, and it should be rigorously tested, because once the data contract is deployed, it cannot be changed.
In most cases, it is the DApp that interacts with the user, so when the control contract is upgraded, the DApp needs to be upgraded to associate it with a new control contract.

Although the contract can be upgraded through the method of this article, we still need to be cautious about upgrading, because upgrading means that you can rewrite the logic, which will reduce the user's trust in you.
The upgrade method introduced in this article is more of an idea, and the actual project may correspond to multiple control contracts and data contracts.

Welcome to my knowledge planet to discuss blockchain technology.

Explain the blockchain in simple terms - learn blockchain systematically and create the best blockchain technology blog.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325376489&siteId=291194637