鍍金池/ 教程/ Linux/ 通用模式
簡(jiǎn)介
編程規(guī)范
雜項(xiàng)
源文件的布局
單位和全局可用變量
合約的結(jié)構(gòu)
通用模式
常見(jiàn)問(wèn)題
深入理解 Solidity
安裝Solidity
智能合約介紹
合約
Solidity 編程實(shí)例
http://solidity.readthedocs.io/en/latest/security-considerations
類型
表達(dá)式和控制結(jié)構(gòu)

通用模式

訪問(wèn)限制

訪問(wèn)限制是合約的一種通用模式,但你不能限制任何人獲取你的合約和交易的狀態(tài)。當(dāng)然,你可以通過(guò)加密來(lái)增加讀取難度,但是如果你的合約需要讀取該數(shù)據(jù)(指加密的數(shù)據(jù)),其他人也可以讀取。

你可以通過(guò)將合約狀態(tài)設(shè)置為私有來(lái)限制其他合約來(lái)讀取你的合約狀態(tài)。

此外,你可以限制其他人修改你的合約狀態(tài)或者調(diào)用你的合約函數(shù),這也是本章將要討論的。

函數(shù)修飾符的使用可以讓這些限制(訪問(wèn)限制)具有較好的可讀性。

contract AccessRestriction {
    // These will be assigned at the construction
    // phase, where `msg.sender` is the account
    // creating this contract.
    //以下變量將在構(gòu)造函數(shù)中賦值 
    //msg.sender是你的賬戶
    //創(chuàng)建本合約
    address public owner = msg.sender;
    uint public creationTime = now;

    // Modifiers can be used to change
    // the body of a function.
    // If this modifier is used, it will
    // prepend a check that only passes
    // if the function is called from
    // a certain address.

//修飾符可以用來(lái)修飾函數(shù)體,如果使用該修飾符,當(dāng)該函數(shù)被其他地址調(diào)用時(shí)將會(huì)先檢查是否允許調(diào)用(譯注:就是說(shuō)外部要調(diào)用本合約有修飾符的函數(shù)時(shí)會(huì)檢查是否允許調(diào)用,比如該函數(shù)是私有的則外部不能調(diào)用。)

    modifier onlyBy(address _account)
    {
        if (msg.sender != _account)
            throw;
        // Do not forget the "_"! It will
        // be replaced by the actual function
        // body when the modifier is invoked.
        //account變量不要忘了“_” 
        _
    }

    /// Make `_newOwner` the new owner of this
    /// contract.
   //修改當(dāng)前合約的宿主
    function changeOwner(address _newOwner)
        onlyBy(owner)
    {
        owner = _newOwner;
    }

    modifier onlyAfter(uint _time) {
        if (now < _time) throw;
        _
    }

    /// Erase ownership information.
    /// May only be called 6 weeks after
    /// the contract has been created.
   //清除宿主信息。只能在合約創(chuàng)建6周后調(diào)用
    function disown()
        onlyBy(owner)
        onlyAfter(creationTime + 6 weeks)
    {
        delete owner;
    }

    // This modifier requires a certain
    // fee being associated with a function call.
    // If the caller sent too much, he or she is
    // refunded, but only after the function body.
    // This is dangerous, because if the function
    // uses `return` explicitly, this will not be
    // done!
    //該修飾符和函數(shù)調(diào)用關(guān)聯(lián)時(shí)需要消耗一部分費(fèi)用。調(diào)用者發(fā)送的多余費(fèi)用會(huì)在函數(shù)執(zhí)行完成后返還,但這個(gè)是相當(dāng)危險(xiǎn)的,因?yàn)槿绻瘮?shù)
    modifier costs(uint _amount) {
        if (msg.value < _amount)
            throw;
        _
        if (msg.value > _amount)
            msg.sender.send(_amount - msg.value);
    }

    function forceOwnerChange(address _newOwner)
        costs(200 ether)
    {
        owner = _newOwner;
        // just some example condition
        if (uint(owner) & 0 == 1)
            // in this case, overpaid fees will not
            // be refunded
            return;
        // otherwise, refund overpaid fees
    }}

A more specialised way in which access to function calls can be restricted will be discussed in the next example.

State Machine Contracts often act as a state machine, which means that they have certain stages in which they behave differently or in which different functions can be called. A function call often ends a stage and transitions the contract into the next stage (especially if the contract models interaction). It is also common that some stages are automatically reached at a certain point in time.

An example for this is a blind auction contract which starts in the stage “accepting blinded bids”, then transitions to “revealing bids” which is ended by “determine auction autcome”.

Function modifiers can be used in this situation to model the states and guard against incorrect usage of the contract.

Example

In the following example, the modifier atStage ensures that the function can only be called at a certain stage.

Automatic timed transitions are handled by the modifier timeTransitions, which should be used for all functions.

Note

Modifier Order Matters. If atStage is combined with timedTransitions, make sure that you mention it after the latter, so that the new stage is taken into account.

Finally, the modifier transitionNext can be used to automatically go to the next stage when the function finishes.

Note

Modifier May be Skipped. Since modifiers are applied by simply replacing code and not by using a function call, the code in the transitionNext modifier can be skipped if the function itself uses return. If you want to do that, make sure to call nextStage manually from those functions.

contract StateMachine {
    enum Stages {
        AcceptingBlindedBids,
        RevealBids,
        AnotherStage,
        AreWeDoneYet,
        Finished
    }
    // This is the current stage.
    Stages public stage = Stages.AcceptingBlindedBids;

    uint public creationTime = now;

    modifier atStage(Stages _stage) {
        if (stage != _stage) throw;
        _
    }
    function nextStage() internal {
        stage = Stages(uint(stage) + 1);
    }
    // Perform timed transitions. Be sure to mention
    // this modifier first, otherwise the guards
    // will not take the new stage into account.
    modifier timedTransitions() {
        if (stage == Stages.AcceptingBlindedBids &&
                    now >= creationTime + 10 days)
            nextStage();
        if (stage == Stages.RevealBids &&
                now >= creationTime + 12 days)
            nextStage();
        // The other stages transition by transaction
    }

    // Order of the modifiers matters here!
    function bid()
        timedTransitions
        atStage(Stages.AcceptingBlindedBids)
    {
        // We will not implement that here
    }
    function reveal()
        timedTransitions
        atStage(Stages.RevealBids)
    {
    }

    // This modifier goes to the next stage
    // after the function is done.
    // If you use `return` in the function,
    // `nextStage` will not be called
    // automatically.
    modifier transitionNext()
    {
        _
        nextStage();
    }
    function g()
        timedTransitions
        atStage(Stages.AnotherStage)
        transitionNext
    {
        // If you want to use `return` here,
        // you have to call `nextStage()` manually.
    }
    function h()
        timedTransitions
        atStage(Stages.AreWeDoneYet)
        transitionNext
    {
    }
    function i()
        timedTransitions
        atStage(Stages.Finished)
    {
    }}

Next Previous