# 【OpenZeppelin】

OpenZeppelin 是一個智能合約庫，其中包含了經過社區審查的 ERC 代幣標準、安全協議以及其他輔助工具，使用 OpenZeppelin 可以極大的提高 Solidity 合約的開發效率並保證合約的安全性。最常用的合約庫如下：

* Ownable：
  * OpenZeppelin 的 Ownable 合約提供的 onlyOwner 模式是用來保護特定合約方法的訪問權限的基礎但非常有效的模式。
* SafeMath：
  * 這個合約會進行所有必要的檢查，避免你的程式碼因算術運算而出現漏洞，或者因為溢位等因素而出現預期外的計算結果。
* SafeCast：
  * 當我們在做型別轉換的時候有可能會出現精度遺漏或者溢位等問題，SafeCast 可以幫我們完成這些轉換而無需擔心溢出問題。
* ERC20/ERC721 等代幣模式

#### Libraries & Using ...

[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)

```solidity
pragma solidity ^0.5.13;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol";

contract LibrariesExample {
    
    using SafeMath for uint;

    mapping(address => uint) public tokenBalance;

    constructor() public {
        tokenBalance[msg.sender] = tokenBalance[msg.sender].add(1);
        // tokenBalance[msg.sender] = 1;
    }

    function sendToken(address _to, uint _amount) public returns(bool) {
        tokenBalance[msg.sender] = tokenBalance[msg.sender].sub(_amount);
        tokenBalance[_to] =  tokenBalance[_to].add(_amount); 
        // tokenBalance[msg.sender] -= _amount;
        // tokenBalance[_to] += _amount;

        return true;
    }
}
```

< 0.8 or >= 0.8 has differnet overfolw and underflow problem

```solidity
pragma solidity >=0.4.16 <0.7.0;

library Search {
    
    function indexOf(uint[] storage self, uint value)
    public
    view
    returns (uint){
        for (uint i = 0; i < self.length; i++)
            if (self[i] == value) return i;
            return uint(-1);
        }
}

contract NotUsingForExample {
    
    uint[] data;
    
    function append(uint value) public {
        data.push(value);    
    }
    
    function replace(uint _old, uint _new) public {
    // This performs the library function call
        uint index = Search.indexOf(data,_old);
        if (index == uint(-1))
            data.push(_new);
        else
            data[index] = _new;
    }
}

contract UsingForExample {
    
    using Search for uint[];
    uint[] data;
    
    function append(uint value) public {
        data.push(value);
    }
    
    function replace(uint _old, uint _new) public {
        // This performs the library function call
        uint index = data.indexOf(_old);
        if (index == uint(-1))
            data.push(_new);
        else
            data[index] = _new;
    }
}
```

使用OpenZeppelin需要特別注意GitHub上的分支，尤其是版本不同在引入到智能合約時會導致編譯錯誤或各種問題。舊版的OpenZeppelin使用上也需要格外小心，因為更新版本有可能是為了修補過往的漏洞或改善品質。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chihaolu.gitbook.io/all-in-one-solidity/part-ii-medium/chapter-13-yin-yong-imports-han-shi-ku-libraries/openzeppelin.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
