Hiring Assistant 4-BEB 1期

10582 ワード

Repository: https://github.com/BuilderBoba/Hiring-Assessment-4-BEB-01


Unit 3-管理者がContractに変更


Contract Address: 0x518c4ecf6aDAc77C7FE098071fd7df2c2A1BFaa5
https://ropsten.etherscan.io/address/0x518c4ecf6aDAc77C7FE098071fd7df2c2A1BFaa5
このインテリジェント契約は、1~3人の管理者のConsensusで実行可能な関数を表すことができる契約です.この知覚機構はOwnHelper sub−contractに含まれる.
初めてスマート契約を実行すると、契約作成者はGenesisOwnerになります.
その後genessisOwnerはaddGenesisOwners(address)関数によって1つまたは2つの追加管理者のアドレスをowners行列に格納することができる.
安全のため、検証用の修飾子を3つ追加できます.
3つの修飾子は次のとおりです.
isGenesisOwner()-見積作成者のみ
onlyOwner()-1~3名のownerアドレスのみ実行可能
agreementonly()-所有者アドレスが一致して同意した場合にのみ実行できます.
たとえば、最初のGenesisOwnerがaddGenesisOwner(address)を介してオフサイトアドレスを追加すると、isGenesisOwner()が修飾子として追加されます.
onlyOwner()関数には、管理してこそいつでも実行できる関数が付属しています.
実際、Consensusメカニズムの適用はagreemently()でのみ発生し、各管理者アドレスのプロトコル情報がAgreementDataデータ型(struct)として格納されると.
struct AgreementData{
        bool yesno;
        string functionCode;
        uint[] parameters;
        string comment;
    }

AgreementData[3] internal ownerAgreements;
また,ownerAgreentsという空間3には,管理者たちのプロトコル情報が組み込まれる.
AgreementDataには、次の4つの情報があります.
bool yesno => 최종적으로 동의하는지 안하는지

string functionCode => 어떤 함수에 대해서 agreement를 논하는건지 알려준다. agreementOnly가 들어가는 특별한 함수들은 전부 고유의 functionCode가 함수 내부에 적혀있다.
    
uint[] parameters => 실행할려는 특정 함수의 세부 입력값도 전원 동의해야한다. 입력값이 필요없으면 빈배열 ([])을 넣으면 되고 있다면 그 값들을 배열 안에 넣으면 된다. 아쉽게도 필자는 아직 초보라 Consensus를 요구하는 함수들의 입력값은 정수여야 한다.
    
string comment => Consenssus 작용에 직접적인 영향을 안미치는 선택적인 항이다. 다른 관리자들에게 자신의 의견을 추가하고 싶을때 사용된다.
AgreementOnly()のコードを見てみましょう.
 modifier agreementOnly(){
        if (_numOwners == 2){
            require(bytes(ownerAgreements[0].functionCode).length > 0 && bytes(ownerAgreements[1].functionCode).length > 0, "Agreement not set");
            require(ownerAgreements[0].yesno == ownerAgreements[1].yesno, "Opinions Do Not Match");
            require(keccak256(bytes(ownerAgreements[0].functionCode)) == keccak256(bytes(ownerAgreements[1].functionCode)), "Functions Do Not Match");
            require(ownerAgreements[0].parameters.length == ownerAgreements[1].parameters.length, "Parameter size do not match");

            for (uint i=0; i<ownerAgreements[0].parameters.length; i++){
                require(ownerAgreements[0].parameters[i] == ownerAgreements[1].parameters[i], "Function Parameters Do Not Match");
            }
        } else if (_numOwners == 3){

            require(bytes(ownerAgreements[0].functionCode).length > 0 && bytes(ownerAgreements[1].functionCode).length > 0
            && bytes(ownerAgreements[2].functionCode).length > 0, "Agreement not set");

            require(ownerAgreements[0].yesno == ownerAgreements[1].yesno && 
            ownerAgreements[0].yesno == ownerAgreements[2].yesno, "Opinions Do Not Match");
            
            require(keccak256(bytes(ownerAgreements[0].functionCode)) == keccak256(bytes(ownerAgreements[1].functionCode)) && 
            keccak256(bytes(ownerAgreements[0].functionCode)) == keccak256(bytes(ownerAgreements[2].functionCode)), "Functions Do Not Match");
            
            require(ownerAgreements[0].parameters.length == ownerAgreements[1].parameters.length
            && ownerAgreements[0].parameters.length == ownerAgreements[2].parameters.length, "Parameter size do not match");

            for (uint i=0; i<ownerAgreements[0].parameters.length; i++){
                require(ownerAgreements[0].parameters[i] == ownerAgreements[1].parameters[i], "Function Parameters Do Not Match");
                require(ownerAgreements[0].parameters[i] == ownerAgreements[2].parameters[i], "Function Parameters Do Not Match");
            }
        }
        _;
    }
簡単に言えば、すべての所有者に存在するアドレスは、互いにAgreementDataのyesno、functionCode、およびパラメータが同じである必要があります.
functioncodeのような文字列変数はエンティティ==で一致しないため、keccak 256(バイト)を使用して==を処理する.
では、AgreementOnlyに内在関数を実行させる方法を見てみましょう.
 function testTwo() onlyOwner agreementOnly public view returns (string memory){
        string memory testTwoCode = "B4";
        require(keccak256(bytes(ownerAgreements[0].functionCode)) == keccak256(bytes(testTwoCode)), "Consensus reached, but wrong function call");
        return "Test Two: multi-sig consensus success";
    }
関数testTwoは入力値のない単純な関数です.
プロトコルのみが成立し、プロトコルがその関数の固有の関数コード「B 4」として成立している場合には、その関数を実行することができる.

testTwo関数を実行する場合は、契約の管理者(owners)がaddAgreement()関数を使用してプロトコルを渡すことができます.ここで、プロトコルを一致させるには、yesno、functioncode、decision値をすべて一致させる必要があります.コメントは伝えたいメッセージを書くことができます.

このようにgetAgreentsでは,3人の条件が一致しなければならない.
yesnoはtrue、関数コードはB 4であり、パラメータには詳細な入力値[]は必要ありません.
これですべてのConsensusがマージされるのでtesttwo関数を実行すると正常に実行されます!
成功!
しかし、3番の管理者が同意しなければどうなりますか?

これにより、エラーが発生し、関数が実行できなくなります.理由は次のとおりです.


Unit 4-Truffleを使用してERC-721を開発


重要な部分は.
Unit_Four/migrations/2_deploy.js
Unit_Four/truffle-config.js
Unit_Four/scampunks_images
Unit_Four/scampunks_metadata
差は多くないでしょう.
NFT Contract Address: 0x1fa9707f1c172A1601A34A887cC37180d76B0acf
https://rinkeby.etherscan.io/address/0x1fa9707f1c172A1601A34A887cC37180d76B0acf
この部分は少し失敗したが,やはり結果が出るだろう.
本来、筆者の計画では、ScramPunksというNFT契約をTruffleとOpenZippelinとして開発し、それをRinkeby Test Networkに配備し、NFTミント処理後のNFTをOpenSEA TestNetと見なす.
まず、メタデータを生成するためにCryptoPunksの3つの画像を取得し、PintaというIPFSファイルマネージャを介してアップロードする.

また、CryptoPunks画像毎にjsonファイルで1つずつ作成し、メタデータに画像のリンクを含めます.

https://gateway.pinata.cloud/ipfs/QmU8Jx2NM3xsELjujt3sLY5abh7rpwjGnGPhS517AGhtBc/0.json
このようにリンクをクリックするだけでメタデータのある場所に行けます
次にScamPunksというフォルダを作成します.
1. truffle init
2. npm init -y
3. npm install @openzeppelin/contracts
4. npm install @truffle/hdwallet-provider
端末で実行し、基本パッケージをインストールしました.
Openzeppelin/contractsに内蔵されています
ERC721PresetMinterPauserAutoId.solを利用する
トークン名、トークンエレメント、トークンURIを入力値として簡単に使用し、独自のNFT Contractを作成します.
// migrations/2_deploy.js
// SPDX-License-Identifier: MIT
const ERC721PresetMinterPauserAutoId = artifacts.require(
  "ERC721PresetMinterPauserAutoId"
);

module.exports = function (deployer) {
  deployer.deploy(
    ERC721PresetMinterPauserAutoId,
    "ScamPunks",
    "SP",
    "https://gateway.pinata.cloud/ipfs/QmU8Jx2NM3xsELjujt3sLY5abh7rpwjGnGPhS517AGhtBc/"
  );
};
配置するプロファイルを作成し、truffle-configを行います.jsはRinkebyネットワークへの接続に必要な情報を変更した.

ここで見たニモニック号はHAのために作っただけなので、心配しないでください.
その後、rinkebyに接続されたtruffleコンソールでmigrateを実行し、作成したContractの導入に成功しました.

ここから最初の問題が発生します.
イーサスキャンに検証ソースコードを追加する方法が分かりません.ご存じのように、私のスマート契約構造はOpenZippelinを使用して作成され、ほとんどの機能がインポートされています.
イーサスキャンの立場では、OpenZeppelinが何なのか、要求されるパッケージが何なのか全く分からないので、純粋なコードを付加する必要があるが、それができなかったため、イーサスキャン内で関数を実現することはできなかった.
だからmint関数の起動は私のTruffleコンソールでしか実行できません.

では、mint関数をこのように実行すると、私のOpenSeaプロファイルの内部に正確に表現されたメタデータと画像があることを望んでいます.
でも...

ScamPunksの名前は本当に値打ちがあります^^


はい、ここで2つ目の問題が発生しました.
配備されたNFTはアップロードされたメタデータを全く反映していない.
まず問題はERC 721プリセットMinterPauserAutoIdです.solでURIを参照する場合、baseURI+tokenIDがデフォルトで参照されます.
例えばbaseURI
https://storage.com/BEB/Scampunks/
tokenIDが11または300の場合、
各参照URI
https://storage.com/BEB/Scampunks/11
https://storage.com/BEB/Scampunks/300
こうなる
残念ながら私のメタデータリンクは最後にありますjsonを含む.
https://gateway.pinata.cloud/ipfs/QmU8Jx2NM3xsELjujt3sLY5abh7rpwjGnGPhS517AGhtBc/ 0.json
https://gateway.pinata.cloud/ipfs/QmU8Jx2NM3xsELjujt3sLY5abh7rpwjGnGPhS517AGhtBc/ 1.json
https://gateway.pinata.cloud/ipfs/QmU8Jx2NM3xsELjujt3sLY5abh7rpwjGnGPhS517AGhtBc/ 2.json
そうですか.

だからURI値を返す関数に行きましたjsonをつけよう!だからこのように书き终わった后に、契约を発表しましたが、しかしやはり失败して、ほほほ...
今週末に必ず解決しなければならない2つの問題

振り返る


うーん、思ったより難しい部分が多かったので、困った時間が多かったようです.Remixという統合環境で開発する場合は、すべての便利なツールを提供する感覚に慣れているかもしれませんが、Truffleを使用してテストネットワークと開発ツールを直接導入する必要がある場合は、多くの問題が発生します.
そのため,Truffleを用いてNFTを開発する過程で多くの問題が発生する可能性がある.
Soledityを学ぶときは「これは本当に便利」という部分がありますが、「わあ、こんな簡単なことはこんなに難しい」という考えもあり、本当に面白い(?)言葉のように
Openzeppelinのcontractソースコードを適用すると、一般的なスマートcontractが開発できるので便利だと思いますが、そうなると、さらにスキャンにソースコードを添付するときに、また慌ててしまいます.
また、エンティティ言語ではstringのデフォルト演算が使用されていないため、x 100000は非常に不快です.
「hi」=「hi」であれば、便利な文字列をバイトデータ型に変換し、それをsha 256ハッシュに変換して比較できてよかったです
とにかくいい経験でした!